46TEST(FunctionInliningTests, testSimpleInlining)
86 auto & graph = rm.
Rvsdg();
87 auto vt = TestType::createValueType();
88 auto iOStateType = IOStateType::Create();
89 auto memoryStateType = MemoryStateType::Create();
92 Region * gammaRegion0 =
nullptr;
97 {
vt, IOStateType::Create(), MemoryStateType::Create() },
98 {
vt, IOStateType::Create(), MemoryStateType::Create() });
101 graph.GetRootRegion(),
102 LlvmLambdaOperation::Create(functionType,
"f1", Linkage::externalLinkage));
103 lambda->AddContextVar(*i);
105 auto t = TestOperation::createNode(
107 { lambda->GetFunctionArguments()[0] },
110 return lambda->finalize(
111 { t->output(0), lambda->GetFunctionArguments()[1], lambda->GetFunctionArguments()[2] });
120 IOStateType::Create(),
121 MemoryStateType::Create() },
122 {
vt, IOStateType::Create(), MemoryStateType::Create() });
125 graph.GetRootRegion(),
126 LlvmLambdaOperation::Create(functionType,
"f2", Linkage::externalLinkage));
127 auto d = lambda->AddContextVar(*f1).inner;
128 auto controlArgument = lambda->GetFunctionArguments()[0];
129 auto valueArgument = lambda->GetFunctionArguments()[1];
130 auto iOStateArgument = lambda->GetFunctionArguments()[2];
131 auto memoryStateArgument = lambda->GetFunctionArguments()[3];
134 gammaRegion0 = gamma->subregion(0);
135 auto gammaInputF1 = gamma->AddEntryVar(d);
136 auto gammaInputValue = gamma->AddEntryVar(valueArgument);
137 auto gammaInputIoState = gamma->AddEntryVar(iOStateArgument);
138 auto gammaInputMemoryState = gamma->AddEntryVar(memoryStateArgument);
140 auto callResults = CallOperation::Create(
141 gammaInputF1.branchArgument[0],
143 { gammaInputValue.branchArgument[0],
144 gammaInputIoState.branchArgument[0],
145 gammaInputMemoryState.branchArgument[0] });
147 auto gammaOutputValue =
148 gamma->AddExitVar({ callResults[0], gammaInputValue.branchArgument[1] });
149 auto gammaOutputIoState =
150 gamma->AddExitVar({ callResults[1], gammaInputIoState.branchArgument[1] });
151 auto gammaOutputMemoryState =
152 gamma->AddExitVar({ callResults[2], gammaInputMemoryState.branchArgument[1] });
154 return lambda->finalize(
155 { gammaOutputValue.output, gammaOutputIoState.output, gammaOutputMemoryState.output });
159 auto f2 = SetupF2(f1);
161 GraphExport::Create(*f2,
"f2");
172 EXPECT_FALSE(Region::containsOperation<CallOperation>(graph.GetRootRegion(),
true));
173 EXPECT_TRUE(Region::containsOperation<TestOperation>(*gammaRegion0,
true));
176 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#Functions"), 2u);
177 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#InlineableFunctions"), 2u);
178 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#FunctionCalls"), 1u);
179 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#InlinableCalls"), 1u);
180 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#CallsInlined"), 1u);
183TEST(FunctionInliningTests, testInliningWithAlloca)
225 auto & graph = rm.
Rvsdg();
226 auto vt = TestType::createValueType();
227 auto iOStateType = IOStateType::Create();
228 auto memoryStateType = MemoryStateType::Create();
231 Region * gammaRegion0 =
nullptr;
232 Region * f2Region =
nullptr;
237 {
vt, IOStateType::Create(), MemoryStateType::Create() },
238 { IOStateType::Create(), MemoryStateType::Create() });
241 graph.GetRootRegion(),
242 LlvmLambdaOperation::Create(functionType,
"f1", Linkage::externalLinkage));
243 lambda->AddContextVar(*i);
244 auto lambdaArgs = lambda->GetFunctionArguments();
246 const auto & one = IntegerConstantOperation::Create(*lambda->subregion(), 32, 1);
247 auto alloca = AllocaOperation::create(
vt, one.output(0), 4);
248 auto store = StoreNonVolatileOperation::Create(alloca[0], lambdaArgs[0], { lambdaArgs[2] }, 4);
250 return lambda->finalize({ lambdaArgs[1], store[0] });
259 IOStateType::Create(),
260 MemoryStateType::Create() },
261 { IOStateType::Create(), MemoryStateType::Create() });
264 graph.GetRootRegion(),
265 LlvmLambdaOperation::Create(functionType,
"f2", Linkage::externalLinkage));
266 auto d = lambda->AddContextVar(*f1).inner;
267 auto controlArgument = lambda->GetFunctionArguments()[0];
268 auto valueArgument = lambda->GetFunctionArguments()[1];
269 auto iOStateArgument = lambda->GetFunctionArguments()[2];
270 auto memoryStateArgument = lambda->GetFunctionArguments()[3];
271 f2Region = lambda->subregion();
274 gammaRegion0 = gamma->subregion(0);
275 auto gammaInputF1 = gamma->AddEntryVar(d);
276 auto gammaInputValue = gamma->AddEntryVar(valueArgument);
277 auto gammaInputIoState = gamma->AddEntryVar(iOStateArgument);
278 auto gammaInputMemoryState = gamma->AddEntryVar(memoryStateArgument);
280 auto callResults = CallOperation::Create(
281 gammaInputF1.branchArgument[0],
283 { gammaInputValue.branchArgument[0],
284 gammaInputIoState.branchArgument[0],
285 gammaInputMemoryState.branchArgument[0] });
287 auto gammaOutputIoState =
288 gamma->AddExitVar({ callResults[0], gammaInputIoState.branchArgument[1] });
289 auto gammaOutputMemoryState =
290 gamma->AddExitVar({ callResults[1], gammaInputMemoryState.branchArgument[1] });
292 return lambda->finalize({ gammaOutputIoState.output, gammaOutputMemoryState.output });
296 auto f2 = SetupF2(f1);
298 GraphExport::Create(*f2,
"f2");
309 EXPECT_FALSE(Region::containsOperation<CallOperation>(graph.GetRootRegion(),
true));
311 EXPECT_TRUE(Region::containsOperation<StoreNonVolatileOperation>(*gammaRegion0,
true));
313 EXPECT_FALSE(Region::containsOperation<AllocaOperation>(*gammaRegion0,
true));
315 EXPECT_TRUE(Region::containsOperation<AllocaOperation>(*f2Region,
false));
318TEST(FunctionInliningTests, testIndirectCall)
330 auto vt = TestType::createValueType();
331 auto iOStateType = IOStateType::Create();
332 auto memoryStateType = MemoryStateType::Create();
335 {
vt, IOStateType::Create(), MemoryStateType::Create() },
336 { IOStateType::Create(), MemoryStateType::Create() });
337 auto pt = PointerType::Create();
340 { PointerType::Create(), IOStateType::Create(), MemoryStateType::Create() },
341 { IOStateType::Create(), MemoryStateType::Create() });
344 auto & graph = rm.Rvsdg();
347 auto SetupF1 = [&](
const std::shared_ptr<const jlm::rvsdg::FunctionType> & functionType)
350 graph.GetRootRegion(),
351 LlvmLambdaOperation::Create(functionType,
"f1", Linkage::externalLinkage));
352 return lambda->finalize(
353 { lambda->GetFunctionArguments()[1], lambda->GetFunctionArguments()[2] });
359 { IOStateType::Create(), MemoryStateType::Create() },
360 { IOStateType::Create(), MemoryStateType::Create() });
363 graph.GetRootRegion(),
364 LlvmLambdaOperation::Create(functionType,
"f2", Linkage::externalLinkage));
365 auto cvi = lambda->AddContextVar(*i).inner;
366 auto cvf1 = lambda->AddContextVar(*f1).inner;
367 auto iOStateArgument = lambda->GetFunctionArguments()[0];
368 auto memoryStateArgument = lambda->GetFunctionArguments()[1];
371 CallOperation::Create(cvi, functionType2, { cvf1, iOStateArgument, memoryStateArgument });
373 return lambda->finalize(callResults);
376 auto f1 = SetupF1(functionType1);
380 GraphExport::Create(*f2,
"f2");
391 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#Functions"), 2u);
392 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#InlineableFunctions"), 2u);
393 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#FunctionCalls"), 1u);
394 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#InlinableCalls"), 0u);
395 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#CallsInlined"), 0u);
402TEST(FunctionInliningTests, testFunctionWithDisqualifyingAlloca)
408 auto vt = TestType::createValueType();
409 auto iOStateType = IOStateType::Create();
410 auto memoryStateType = MemoryStateType::Create();
413 auto & graph = rm.
Rvsdg();
417 auto functionType = FunctionType::Create(
418 { IOStateType::Create(), MemoryStateType::Create() },
419 { IOStateType::Create(), MemoryStateType::Create() });
422 graph.GetRootRegion(),
423 LlvmLambdaOperation::Create(functionType,
"f1", Linkage::externalLinkage));
424 auto theta = ThetaNode::create(lambda->subregion());
426 const auto & one = IntegerConstantOperation::Create(*theta->subregion(), 32, 1);
427 AllocaOperation::create(
vt, one.output(0), 4);
429 return lambda->finalize(
430 { lambda->GetFunctionArguments()[0], lambda->GetFunctionArguments()[1] });
438 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#Functions"), 1u);
440 EXPECT_EQ(statistics->GetMeasurementValue<uint64_t>(
"#InlineableFunctions"), 0u);
443TEST(FunctionInliningTests, testIOBarrierInsertion)
450 auto & graph = rvsdgModule.
Rvsdg();
452 auto vt = TestType::createValueType();
453 auto i32Type = BitType::Create(32);
454 auto pointerType = PointerType::Create();
455 auto iOStateType = IOStateType::Create();
456 auto memoryStateType = MemoryStateType::Create();
460 auto deltaNode = DeltaNode::Create(
461 &graph.GetRootRegion(),
462 LlvmDeltaOperation::Create(i32Type,
"delta", Linkage::externalLinkage,
"",
true, 4));
463 auto & constant = IntegerConstantOperation::Create(*deltaNode->subregion(), 32, 4);
464 deltaNode->finalize(constant.output(0));
468 auto SetupF1 = [&](
Output * d1)
470 auto functionType = FunctionType::Create(
471 { pointerType, IOStateType::Create(), MemoryStateType::Create() },
472 { i32Type, i32Type, IOStateType::Create(), MemoryStateType::Create() });
474 auto lambda = LambdaNode::Create(
475 graph.GetRootRegion(),
476 LlvmLambdaOperation::Create(functionType,
"f1", Linkage::externalLinkage));
477 auto ctxVar = lambda->AddContextVar(*d1);
478 auto ptrArgument = lambda->GetFunctionArguments()[0];
479 auto ioStateArgument = lambda->GetFunctionArguments()[1];
480 auto memoryStateArgument = lambda->GetFunctionArguments()[2];
483 LoadNonVolatileOperation::CreateNode(*ptrArgument, { memoryStateArgument }, i32Type, 4);
486 LoadNonVolatileOperation::CreateNode(*ctxVar.inner, { loadNode1.output(1) }, i32Type, 4);
488 return lambda->finalize(
489 { loadNode1.output(0), loadNode2.output(0), ioStateArgument, loadNode2.output(1) });
492 auto SetupF2 = [&](
Output * f1)
494 auto ct = ControlType::Create(2);
495 auto functionType = FunctionType::Create(
496 { pointerType, IOStateType::Create(), MemoryStateType::Create() },
497 { i32Type, i32Type, IOStateType::Create(), MemoryStateType::Create() });
499 auto lambda = LambdaNode::Create(
500 graph.GetRootRegion(),
501 LlvmLambdaOperation::Create(functionType,
"f2", Linkage::externalLinkage));
502 auto ctxVar = lambda->AddContextVar(*f1);
503 auto ptrArgument = lambda->GetFunctionArguments()[0];
504 auto iOStateArgument = lambda->GetFunctionArguments()[1];
505 auto memoryStateArgument = lambda->GetFunctionArguments()[2];
507 auto callResults = CallOperation::Create(
510 { ptrArgument, iOStateArgument, memoryStateArgument });
512 lambda->finalize({ callResults[0], callResults[1], callResults[2], callResults[3] });
517 auto f1 = SetupF1(&d1->output());
518 auto f2 = SetupF2(f1);
520 GraphExport::Create(*f2->output(),
"f2");
527 EXPECT_FALSE(Region::containsOperation<CallOperation>(graph.GetRootRegion(),
true));
530 EXPECT_EQ(f2->subregion()->numNodes(), 4);
533 auto [loadNode, loadOp] = TryGetSimpleNodeAndOptionalOp<LoadNonVolatileOperation>(
534 *f2->GetFunctionResults()[0]->origin());
535 EXPECT_NE(loadOp,
nullptr);
537 auto [ioBarrierNode, ioBarrierOp] = TryGetSimpleNodeAndOptionalOp<IOBarrierOperation>(
538 *LoadOperation::AddressInput(*loadNode).origin());
539 EXPECT_NE(ioBarrierOp,
nullptr);
540 EXPECT_EQ(ioBarrierNode->input(1)->origin(), f2->GetFunctionArguments()[1]);
544 auto [loadNode, loadOp] = TryGetSimpleNodeAndOptionalOp<LoadNonVolatileOperation>(
545 *f2->GetFunctionResults()[1]->origin());
546 EXPECT_NE(loadOp,
nullptr);
548 auto [ioBarrierNode, ioBarrierOp] = TryGetSimpleNodeAndOptionalOp<IOBarrierOperation>(
549 *LoadOperation::AddressInput(*loadNode).origin());
550 EXPECT_NE(ioBarrierOp,
nullptr);
551 EXPECT_EQ(ioBarrierNode->input(1)->origin(), f2->GetFunctionArguments()[1]);