Jlm
Loading...
Searching...
No Matches
CallSummaryTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#include <gtest/gtest.h>
7
16
17TEST(CallSummaryTests, TestCallSummaryComputationDead)
18{
19 using namespace jlm;
20
21 // Arrange
22 auto vt = rvsdg::TestType::createValueType();
23 auto functionType = jlm::rvsdg::FunctionType::Create({}, { vt });
24
25 auto rvsdgModule = jlm::llvm::LlvmRvsdgModule::Create(util::FilePath(""), "", "");
26 auto & rvsdg = rvsdgModule->Rvsdg();
27
28 auto lambdaNode = jlm::rvsdg::LambdaNode::Create(
29 rvsdg.GetRootRegion(),
31 functionType,
32 "f",
34
35 auto result = rvsdg::TestOperation::createNode(lambdaNode->subregion(), {}, { vt })->output(0);
36
37 lambdaNode->finalize({ result });
38
39 // Act
40 auto callSummary = jlm::llvm::ComputeCallSummary(*lambdaNode);
41
42 // Assert
43 EXPECT_TRUE(callSummary.IsDead());
44
45 EXPECT_FALSE(callSummary.IsExported());
46 EXPECT_FALSE(callSummary.IsOnlyExported());
47 EXPECT_EQ(callSummary.GetRvsdgExport(), nullptr);
48 EXPECT_FALSE(callSummary.HasOnlyDirectCalls());
49}
50
51TEST(CallSummaryTests, TestCallSummaryComputationExport)
52{
53 using namespace jlm;
54
55 // Arrange
56 auto vt = rvsdg::TestType::createValueType();
57 auto functionType = jlm::rvsdg::FunctionType::Create({}, { vt });
58
59 auto rvsdgModule = jlm::llvm::LlvmRvsdgModule::Create(util::FilePath(""), "", "");
60 auto & rvsdg = rvsdgModule->Rvsdg();
61
62 auto lambdaNode = jlm::rvsdg::LambdaNode::Create(
63 rvsdg.GetRootRegion(),
65 functionType,
66 "f",
68
69 auto result = rvsdg::TestOperation::createNode(lambdaNode->subregion(), {}, { vt })->output(0);
70
71 auto lambdaOutput = lambdaNode->finalize({ result });
72 auto & rvsdgExport = rvsdg::GraphExport::Create(*lambdaOutput, "f");
73
74 // Act
75 auto callSummary = jlm::llvm::ComputeCallSummary(*lambdaNode);
76
77 // Assert
78 EXPECT_TRUE(callSummary.IsExported());
79 EXPECT_TRUE(callSummary.IsOnlyExported());
80 EXPECT_EQ(callSummary.GetRvsdgExport(), &rvsdgExport);
81
82 EXPECT_FALSE(callSummary.IsDead());
83 EXPECT_FALSE(callSummary.HasOnlyDirectCalls());
84}
85
86TEST(CallSummaryTests, TestCallSummaryComputationDirectCalls)
87{
88 using namespace jlm;
89
90 // Arrange
91 auto vt = rvsdg::TestType::createValueType();
92 auto functionType = jlm::rvsdg::FunctionType::Create(
95
96 auto rvsdgModule = jlm::llvm::LlvmRvsdgModule::Create(util::FilePath(""), "", "");
97 auto & rvsdg = rvsdgModule->Rvsdg();
98
99 auto SetupLambdaX = [&]()
100 {
101 auto lambdaNode = jlm::rvsdg::LambdaNode::Create(
102 rvsdg.GetRootRegion(),
104 functionType,
105 "x",
107 auto iOStateArgument = lambdaNode->GetFunctionArguments()[0];
108 auto memoryStateArgument = lambdaNode->GetFunctionArguments()[1];
109
110 auto result = rvsdg::TestOperation::createNode(lambdaNode->subregion(), {}, { vt })->output(0);
111
112 return lambdaNode->finalize({ result, iOStateArgument, memoryStateArgument });
113 };
114
115 auto SetupLambdaY = [&](rvsdg::Output & lambdaX)
116 {
117 auto lambdaNode = jlm::rvsdg::LambdaNode::Create(
118 rvsdg.GetRootRegion(),
120 functionType,
121 "y",
123 auto iOStateArgument = lambdaNode->GetFunctionArguments()[0];
124 auto memoryStateArgument = lambdaNode->GetFunctionArguments()[1];
125 auto lambdaXCv = lambdaNode->AddContextVar(lambdaX).inner;
126
127 auto callResults = jlm::llvm::CallOperation::Create(
128 lambdaXCv,
129 functionType,
130 { iOStateArgument, memoryStateArgument });
131
132 auto lambdaOutput = lambdaNode->finalize(callResults);
133 rvsdg::GraphExport::Create(*lambdaOutput, "y");
134
135 return lambdaOutput;
136 };
137
138 auto SetupLambdaZ = [&](rvsdg::Output & lambdaX, rvsdg::Output & lambdaY)
139 {
140 auto lambdaNode = jlm::rvsdg::LambdaNode::Create(
141 rvsdg.GetRootRegion(),
143 functionType,
144 "y",
146 auto iOStateArgument = lambdaNode->GetFunctionArguments()[0];
147 auto memoryStateArgument = lambdaNode->GetFunctionArguments()[1];
148 auto lambdaXCv = lambdaNode->AddContextVar(lambdaX).inner;
149 auto lambdaYCv = lambdaNode->AddContextVar(lambdaY).inner;
150
151 auto callXResults = jlm::llvm::CallOperation::Create(
152 lambdaXCv,
153 functionType,
154 { iOStateArgument, memoryStateArgument });
155 auto callYResults = jlm::llvm::CallOperation::Create(
156 lambdaYCv,
157 functionType,
158 { callXResults[1], callXResults[2] });
159
160 auto result = rvsdg::TestOperation::createNode(
161 lambdaNode->subregion(),
162 { callXResults[0], callYResults[0] },
163 { vt })
164 ->output(0);
165
166 auto lambdaOutput = lambdaNode->finalize({ result, callYResults[1], callYResults[2] });
167 rvsdg::GraphExport::Create(*lambdaOutput, "z");
168
169 return lambdaOutput;
170 };
171
172 auto lambdaX = SetupLambdaX();
173 auto lambdaY = SetupLambdaY(*lambdaX);
174 auto lambdaZ = SetupLambdaZ(*lambdaX, *lambdaY);
175
176 // Act
177 auto lambdaXCallSummary =
178 jlm::llvm::ComputeCallSummary(rvsdg::AssertGetOwnerNode<jlm::rvsdg::LambdaNode>(*lambdaX));
179 auto lambdaYCallSummary =
180 jlm::llvm::ComputeCallSummary(rvsdg::AssertGetOwnerNode<jlm::rvsdg::LambdaNode>(*lambdaY));
181 auto lambdaZCallSummary =
182 jlm::llvm::ComputeCallSummary(rvsdg::AssertGetOwnerNode<jlm::rvsdg::LambdaNode>(*lambdaZ));
183
184 // Assert
185 EXPECT_TRUE(lambdaXCallSummary.HasOnlyDirectCalls());
186 EXPECT_EQ(lambdaXCallSummary.NumDirectCalls(), 2u);
187 EXPECT_FALSE(lambdaXCallSummary.IsDead());
188 EXPECT_FALSE(lambdaXCallSummary.IsExported());
189 EXPECT_FALSE(lambdaXCallSummary.IsOnlyExported());
190
191 EXPECT_FALSE(lambdaYCallSummary.IsDead());
192 EXPECT_FALSE(lambdaYCallSummary.HasOnlyDirectCalls());
193 EXPECT_EQ(lambdaYCallSummary.NumDirectCalls(), 1u);
194 EXPECT_TRUE(lambdaYCallSummary.IsExported());
195 EXPECT_FALSE(lambdaYCallSummary.IsOnlyExported());
196
197 EXPECT_FALSE(lambdaZCallSummary.IsDead());
198 EXPECT_FALSE(lambdaZCallSummary.HasOnlyDirectCalls());
199 EXPECT_EQ(lambdaZCallSummary.NumDirectCalls(), 0u);
200 EXPECT_TRUE(lambdaZCallSummary.IsExported());
201 EXPECT_TRUE(lambdaZCallSummary.IsOnlyExported());
202}
203
204TEST(CallSummaryTests, TestCallSummaryComputationIndirectCalls)
205{
206 using namespace jlm::llvm;
207
208 // Arrange
210 test.module();
211
212 // Act
213 auto lambdaThreeCallSummary = jlm::llvm::ComputeCallSummary(test.GetLambdaThree());
214 auto lambdaFourCallSummary = jlm::llvm::ComputeCallSummary(test.GetLambdaFour());
215 auto lambdaIndcallCallSummary = jlm::llvm::ComputeCallSummary(test.GetLambdaIndcall());
216 auto lambdaTestCallSummary = jlm::llvm::ComputeCallSummary(test.GetLambdaTest());
217
218 // Assert
219 EXPECT_FALSE(lambdaThreeCallSummary.HasOnlyDirectCalls());
220 EXPECT_EQ(lambdaThreeCallSummary.NumDirectCalls(), 0u);
221 EXPECT_FALSE(lambdaThreeCallSummary.IsDead());
222 EXPECT_FALSE(lambdaThreeCallSummary.IsExported());
223 EXPECT_FALSE(lambdaThreeCallSummary.IsOnlyExported());
224 EXPECT_EQ(lambdaThreeCallSummary.NumOtherUsers(), 1u);
225
226 EXPECT_FALSE(lambdaFourCallSummary.HasOnlyDirectCalls());
227 EXPECT_EQ(lambdaFourCallSummary.NumDirectCalls(), 0u);
228 EXPECT_FALSE(lambdaFourCallSummary.IsDead());
229 EXPECT_FALSE(lambdaFourCallSummary.IsExported());
230 EXPECT_FALSE(lambdaFourCallSummary.IsOnlyExported());
231 EXPECT_EQ(lambdaFourCallSummary.NumOtherUsers(), 1u);
232
233 EXPECT_TRUE(lambdaIndcallCallSummary.HasOnlyDirectCalls());
234 EXPECT_EQ(lambdaIndcallCallSummary.NumDirectCalls(), 2u);
235 EXPECT_FALSE(lambdaIndcallCallSummary.IsDead());
236 EXPECT_FALSE(lambdaIndcallCallSummary.IsExported());
237 EXPECT_FALSE(lambdaIndcallCallSummary.IsOnlyExported());
238 EXPECT_EQ(lambdaIndcallCallSummary.NumOtherUsers(), 0u);
239
240 EXPECT_FALSE(lambdaTestCallSummary.HasOnlyDirectCalls());
241 EXPECT_EQ(lambdaTestCallSummary.NumDirectCalls(), 0u);
242 EXPECT_FALSE(lambdaTestCallSummary.IsDead());
243 EXPECT_TRUE(lambdaTestCallSummary.IsExported());
244 EXPECT_TRUE(lambdaTestCallSummary.IsOnlyExported());
245 EXPECT_EQ(lambdaTestCallSummary.NumOtherUsers(), 0u);
246}
247
248TEST(CallSummaryTests, TestCallSummaryComputationFunctionPointerInDelta)
249{
250 using namespace jlm::llvm;
251
252 // Arrange
253 auto rvsdgModule = LlvmRvsdgModule::Create(jlm::util::FilePath(""), "", "");
254 auto rvsdg = &rvsdgModule->Rvsdg();
255
256 auto valueType = jlm::rvsdg::TestType::createValueType();
257 auto functionType = jlm::rvsdg::FunctionType::Create({ valueType }, { valueType });
258
259 auto lambdaNode = jlm::rvsdg::LambdaNode::Create(
260 rvsdg->GetRootRegion(),
261 LlvmLambdaOperation::Create(functionType, "f", Linkage::externalLinkage));
262 lambdaNode->finalize({ lambdaNode->GetFunctionArguments()[0] });
263
264 auto deltaNode = jlm::rvsdg::DeltaNode::Create(
265 &rvsdg->GetRootRegion(),
266 LlvmDeltaOperation::Create(functionType, "fp", Linkage::externalLinkage, "", false, 4));
267 auto argument = deltaNode->AddContextVar(*lambdaNode->output()).inner;
268 deltaNode->finalize(argument);
269
270 jlm::rvsdg::GraphExport::Create(deltaNode->output(), "fp");
271
272 // Act
273 auto callSummary = jlm::llvm::ComputeCallSummary(*lambdaNode);
274
275 // Assert
276 EXPECT_EQ(callSummary.NumOtherUsers(), 1u);
277 EXPECT_TRUE(callSummary.HasOnlyOtherUsages());
278}
279
280TEST(CallSummaryTests, TestCallSummaryComputationLambdaResult)
281{
282 using namespace jlm::llvm;
283
284 // Arrange
285 jlm::rvsdg::Graph rvsdg;
286
287 auto pointerType = PointerType::Create();
288 auto valueType = jlm::rvsdg::TestType::createValueType();
289 auto functionTypeG = jlm::rvsdg::FunctionType::Create({ valueType }, { valueType });
290 auto functionTypeF = jlm::rvsdg::FunctionType::Create({ valueType }, { PointerType::Create() });
291
292 auto lambdaNodeG = jlm::rvsdg::LambdaNode::Create(
293 rvsdg.GetRootRegion(),
294 jlm::llvm::LlvmLambdaOperation::Create(functionTypeG, "g", Linkage::externalLinkage));
295 auto lambdaOutputG = lambdaNodeG->finalize({ lambdaNodeG->GetFunctionArguments()[0] });
296
297 auto lambdaNodeF = jlm::rvsdg::LambdaNode::Create(
298 rvsdg.GetRootRegion(),
299 jlm::llvm::LlvmLambdaOperation::Create(functionTypeF, "f", Linkage::externalLinkage));
300 auto lambdaGArgument = lambdaNodeF->AddContextVar(*lambdaOutputG).inner;
301 auto ptr =
302 jlm::rvsdg::CreateOpNode<FunctionToPointerOperation>({ lambdaGArgument }, functionTypeG)
303 .output(0);
304 auto lambdaOutputF = lambdaNodeF->finalize({ ptr });
305
306 jlm::rvsdg::GraphExport::Create(*lambdaOutputF, "f");
307
308 // Act
309 auto callSummary = jlm::llvm::ComputeCallSummary(*lambdaNodeG);
310
311 // Assert
312 EXPECT_EQ(callSummary.NumOtherUsers(), 1u);
313 EXPECT_TRUE(callSummary.HasOnlyOtherUsages());
314}
TEST(CallSummaryTests, TestCallSummaryComputationDead)
static const auto vt
Definition PullTests.cpp:16
static std::vector< rvsdg::Output * > Create(rvsdg::Output *function, std::shared_ptr< const rvsdg::FunctionType > functionType, const std::vector< rvsdg::Output * > &arguments)
Definition call.hpp:464
static std::shared_ptr< const IOStateType > Create()
Definition types.cpp:343
IndirectCallTest1 class.
const jlm::rvsdg::LambdaNode & GetLambdaFour() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaThree() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaTest() const noexcept
const jlm::rvsdg::LambdaNode & GetLambdaIndcall() const noexcept
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)
Definition lambda.hpp:84
static std::unique_ptr< LlvmRvsdgModule > Create(const util::FilePath &sourceFileName, const std::string &targetTriple, const std::string &dataLayout)
static std::shared_ptr< const MemoryStateType > Create()
Definition types.cpp:379
jlm::llvm::LlvmRvsdgModule & module()
static DeltaNode * Create(rvsdg::Region *parent, std::unique_ptr< DeltaOperation > op)
Definition delta.hpp:313
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 GraphExport & Create(Output &origin, std::string name)
Definition graph.cpp:62
Region & GetRootRegion() const noexcept
Definition graph.hpp:99
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition lambda.cpp:141
static std::shared_ptr< const TestType > createValueType()
Definition TestType.cpp:67
Global memory state passed between functions.
CallSummary ComputeCallSummary(const rvsdg::LambdaNode &lambdaNode)
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872