62TEST(CallOperationTests, TestCallNodeAccessors)
68 auto valueType = TestType::createValueType();
69 auto iOStateType = IOStateType::Create();
70 auto memoryStateType = MemoryStateType::Create();
72 { valueType, IOStateType::Create(), MemoryStateType::Create() },
73 { valueType, IOStateType::Create(), MemoryStateType::Create() });
82 auto results = CallOperation::Create(f, functionType, { v, i, m });
87 EXPECT_EQ(CallOperation::NumArguments(callNode), 3u);
88 EXPECT_EQ(CallOperation::NumArguments(callNode), callNode.ninputs() - 1);
89 EXPECT_EQ(CallOperation::Argument(callNode, 0u)->origin(), v);
90 EXPECT_EQ(CallOperation::Argument(callNode, 1u)->origin(), i);
91 EXPECT_EQ(CallOperation::Argument(callNode, 2u)->origin(), m);
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);
98 EXPECT_EQ(CallOperation::GetFunctionInput(callNode).origin(), f);
99 EXPECT_EQ(CallOperation::GetIOStateInput(callNode).origin(), i);
100 EXPECT_EQ(CallOperation::GetMemoryStateInput(callNode).origin(), m);
102 EXPECT_EQ(*CallOperation::GetIOStateOutput(callNode).
Type(), *iOStateType);
103 EXPECT_EQ(*CallOperation::GetMemoryStateOutput(callNode).
Type(), *memoryStateType);
106TEST(CallOperationTests, TestCallTypeClassifierIndirectCall)
112 auto iOStateType = IOStateType::Create();
113 auto memoryStateType = MemoryStateType::Create();
115 { IOStateType::Create(), MemoryStateType::Create() },
116 {
vt, IOStateType::Create(), MemoryStateType::Create() });
118 { PointerType::Create(), IOStateType::Create(), MemoryStateType::Create() },
119 {
vt, IOStateType::Create(), MemoryStateType::Create() });
121 auto module = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
122 auto graph = &
module->Rvsdg();
124 auto SetupFunction = [&]()
127 graph->GetRootRegion(),
128 LlvmLambdaOperation::Create(fcttype2,
"fct", Linkage::externalLinkage));
129 auto iOStateArgument = lambda->GetFunctionArguments()[1];
130 auto memoryStateArgument = lambda->GetFunctionArguments()[2];
134 auto alloca = AllocaOperation::create(PointerType::Create(), one, 8);
136 auto store = StoreNonVolatileOperation::Create(
138 lambda->GetFunctionArguments()[0],
142 auto load = LoadNonVolatileOperation::Create(alloca[0], store, PointerType::Create(), 8);
146 CallOperation::Create(fn, fcttype1, { iOStateArgument, memoryStateArgument });
148 lambda->finalize(callResults);
152 return std::make_tuple(
153 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
158 auto [callNode, loadOutput] = SetupFunction();
161 auto callTypeClassifier = CallOperation::ClassifyCall(*callNode);
164 EXPECT_TRUE(callTypeClassifier->IsIndirectCall());
165 EXPECT_EQ(loadOutput, &callTypeClassifier->GetFunctionOrigin());
168TEST(CallOperationTests, TestCallTypeClassifierNonRecursiveDirectCall)
174 auto module = jlm::llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
175 auto graph = &
module->Rvsdg();
178 auto iOStateType = IOStateType::Create();
179 auto memoryStateType = MemoryStateType::Create();
182 { IOStateType::Create(), MemoryStateType::Create() },
183 {
vt, IOStateType::Create(), MemoryStateType::Create() });
185 auto SetupFunctionG = [&]()
188 graph->GetRootRegion(),
189 LlvmLambdaOperation::Create(functionTypeG,
"g", Linkage::externalLinkage));
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);
223 auto iOStateType = IOStateType::Create();
224 auto memoryStateType = MemoryStateType::Create();
227 { IOStateType::Create(), MemoryStateType::Create() },
228 {
vt, IOStateType::Create(), MemoryStateType::Create() });
231 graph->GetRootRegion(),
232 LlvmLambdaOperation::Create(functionType,
"f", Linkage::externalLinkage));
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);
239 auto callResults = CallOperation::Create(
242 { iOStateArgument, memoryStateArgument });
244 lambda->finalize(callResults);
246 return std::make_tuple(
248 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
252 auto g = SetupFunctionG();
253 auto [f, callNode] = SetupFunctionF(g);
260 auto callTypeClassifier = CallOperation::ClassifyCall(*callNode);
263 EXPECT_TRUE(callTypeClassifier->IsNonRecursiveDirectCall());
264 EXPECT_EQ(&callTypeClassifier->GetLambdaOutput(), g);
267TEST(CallOperationTests, TestCallTypeClassifierNonRecursiveDirectCallTheta)
273 auto module = jlm::llvm::LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
274 auto graph = &
module->Rvsdg();
277 auto iOStateType = IOStateType::Create();
278 auto memoryStateType = MemoryStateType::Create();
281 { IOStateType::Create(), MemoryStateType::Create() },
282 {
vt, IOStateType::Create(), MemoryStateType::Create() });
284 auto SetupFunctionG = [&]()
287 graph->GetRootRegion(),
288 LlvmLambdaOperation::Create(functionTypeG,
"g", Linkage::externalLinkage));
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);
321 auto callResults = CallOperation::Create(
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>(
340 auto iOStateType = IOStateType::Create();
341 auto memoryStateType = MemoryStateType::Create();
344 { IOStateType::Create(), MemoryStateType::Create() },
345 {
vt, IOStateType::Create(), MemoryStateType::Create() });
348 graph->GetRootRegion(),
349 LlvmLambdaOperation::Create(functionType,
"f", Linkage::externalLinkage));
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);
375 auto callTypeClassifier = CallOperation::ClassifyCall(*callNode);
378 EXPECT_TRUE(callTypeClassifier->IsNonRecursiveDirectCall());
379 EXPECT_EQ(&callTypeClassifier->GetLambdaOutput(), g);
382TEST(CallOperationTests, TestCallTypeClassifierRecursiveDirectCall)
387 auto module = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
388 auto graph = &
module->Rvsdg();
390 auto SetupFib = [&]()
392 auto iOStateType = IOStateType::Create();
393 auto memoryStateType = MemoryStateType::Create();
396 PointerType::Create(),
397 IOStateType::Create(),
398 MemoryStateType::Create() },
399 { IOStateType::Create(), MemoryStateType::Create() });
400 auto pt = PointerType::Create();
403 pb.
begin(&graph->GetRootRegion());
408 LlvmLambdaOperation::Create(functionType,
"fib", Linkage::externalLinkage));
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);
429 auto callfibm1Results = CallOperation::Create(
430 fibev.branchArgument[0],
433 resultev.branchArgument[0],
434 gIIoState.branchArgument[0],
435 gIMemoryState.branchArgument[0] });
439 auto callfibm2Results = CallOperation::Create(
440 fibev.branchArgument[0],
442 { nm2, resultev.branchArgument[0], callfibm1Results[0], callfibm1Results[1] });
444 auto gepnm1 = GetElementPtrOperation::create(
445 resultev.branchArgument[0],
448 auto ldnm1 = LoadNonVolatileOperation::Create(
450 { callfibm2Results[1] },
454 auto gepnm2 = GetElementPtrOperation::create(
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] });
470 auto gepn = GetElementPtrOperation::create(
474 auto store = StoreNonVolatileOperation::Create(gepn, sumex.output, { gOMemoryState.output }, 8);
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>(
487 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(
491 auto [fibfct, callFib1, callFib2] = SetupFib();
494 auto callTypeClassifier1 = CallOperation::ClassifyCall(*callFib1);
495 auto callTypeClassifier2 = CallOperation::ClassifyCall(*callFib2);
498 EXPECT_TRUE(callTypeClassifier1->IsRecursiveDirectCall());
499 EXPECT_EQ(&callTypeClassifier1->GetLambdaOutput(), fibfct);
501 EXPECT_TRUE(callTypeClassifier2->IsRecursiveDirectCall());
502 EXPECT_EQ(&callTypeClassifier2->GetLambdaOutput(), fibfct);