Jlm
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 
13 #include <jlm/llvm/TestRvsdgs.hpp>
15 #include <jlm/rvsdg/TestType.hpp>
16 
17 TEST(CallSummaryTests, TestCallSummaryComputationDead)
18 {
19  using namespace jlm;
20 
21  // Arrange
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 
51 TEST(CallSummaryTests, TestCallSummaryComputationExport)
52 {
53  using namespace jlm;
54 
55  // Arrange
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 
86 TEST(CallSummaryTests, TestCallSummaryComputationDirectCalls)
87 {
88  using namespace jlm;
89 
90  // Arrange
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 
204 TEST(CallSummaryTests, TestCallSummaryComputationIndirectCalls)
205 {
206  using namespace jlm::llvm;
207 
208  // Arrange
209  IndirectCallTest1 test;
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 
248 TEST(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(),
262  lambdaNode->finalize({ lambdaNode->GetFunctionArguments()[0] });
263 
264  auto deltaNode = jlm::rvsdg::DeltaNode::Create(
265  &rvsdg->GetRootRegion(),
267  functionType,
268  "fp",
270  "",
271  false,
272  4));
273  auto argument = deltaNode->AddContextVar(*lambdaNode->output()).inner;
274  deltaNode->finalize(argument);
275 
276  jlm::rvsdg::GraphExport::Create(deltaNode->output(), "fp");
277 
278  // Act
279  auto callSummary = jlm::llvm::ComputeCallSummary(*lambdaNode);
280 
281  // Assert
282  EXPECT_EQ(callSummary.NumOtherUsers(), 1u);
283  EXPECT_TRUE(callSummary.HasOnlyOtherUsages());
284 }
285 
286 TEST(CallSummaryTests, TestCallSummaryComputationLambdaResult)
287 {
288  using namespace jlm::llvm;
289 
290  // Arrange
291  jlm::rvsdg::Graph rvsdg;
292 
293  auto pointerType = PointerType::Create();
294  auto valueType = jlm::rvsdg::TestType::createValueType();
295  auto functionTypeG = jlm::rvsdg::FunctionType::Create({ valueType }, { valueType });
296  auto functionTypeF = jlm::rvsdg::FunctionType::Create({ valueType }, { PointerType::Create() });
297 
298  auto lambdaNodeG = jlm::rvsdg::LambdaNode::Create(
299  rvsdg.GetRootRegion(),
301  auto lambdaOutputG = lambdaNodeG->finalize({ lambdaNodeG->GetFunctionArguments()[0] });
302 
303  auto lambdaNodeF = jlm::rvsdg::LambdaNode::Create(
304  rvsdg.GetRootRegion(),
306  auto lambdaGArgument = lambdaNodeF->AddContextVar(*lambdaOutputG).inner;
307  auto ptr =
308  jlm::rvsdg::CreateOpNode<FunctionToPointerOperation>({ lambdaGArgument }, functionTypeG)
309  .output(0);
310  auto lambdaOutputF = lambdaNodeF->finalize({ ptr });
311 
312  jlm::rvsdg::GraphExport::Create(*lambdaOutputF, "f");
313 
314  // Act
315  auto callSummary = jlm::llvm::ComputeCallSummary(*lambdaNodeG);
316 
317  // Assert
318  EXPECT_EQ(callSummary.NumOtherUsers(), 1u);
319  EXPECT_TRUE(callSummary.HasOnlyOtherUsages());
320 }
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::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)
Definition: delta.hpp:84
static std::shared_ptr< const IOStateType > Create()
Definition: types.cpp:343
IndirectCallTest1 class.
Definition: TestRvsdgs.hpp:566
const jlm::rvsdg::LambdaNode & GetLambdaTest() const noexcept
Definition: TestRvsdgs.hpp:605
const jlm::rvsdg::LambdaNode & GetLambdaIndcall() const noexcept
Definition: TestRvsdgs.hpp:599
const jlm::rvsdg::LambdaNode & GetLambdaFour() const noexcept
Definition: TestRvsdgs.hpp:593
const jlm::rvsdg::LambdaNode & GetLambdaThree() const noexcept
Definition: TestRvsdgs.hpp:587
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
static std::shared_ptr< const PointerType > Create()
Definition: types.cpp:45
jlm::llvm::LlvmRvsdgModule & module()
Definition: TestRvsdgs.hpp:34
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:140
NodeOutput * output(size_t index) const noexcept
Definition: simple-node.hpp:88
static SimpleNode * createNode(Region *region, const std::vector< Output * > &operands, std::vector< std::shared_ptr< const Type >> resultTypes)
static std::shared_ptr< const TestType > createValueType()
Definition: TestType.cpp:67
Global memory state passed between functions.
CallSummary ComputeCallSummary(const rvsdg::LambdaNode &lambdaNode)
Definition: CallSummary.cpp:30