Jlm
CallSummary.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018 Nico Reißmann <nico.reissmann@gmail.com>
3  * Copyright 2025 Helge Bahmann <hcb@chaoticmind.net>
4  * See COPYING for terms of redistribution.
5  */
6 
8 
11 #include <jlm/rvsdg/gamma.hpp>
12 #include <jlm/rvsdg/Phi.hpp>
13 #include <jlm/rvsdg/theta.hpp>
14 
15 #include <deque>
16 
17 namespace jlm::llvm
18 {
19 
20 static void
21 AddToWorklist(std::deque<rvsdg::Input *> & worklist, rvsdg::Output & output)
22 {
23  for (auto & user : output.Users())
24  {
25  worklist.emplace_back(&user);
26  }
27 }
28 
29 CallSummary
31 {
32  std::deque<rvsdg::Input *> worklist;
33  AddToWorklist(worklist, *lambdaNode.output());
34 
35  std::vector<rvsdg::SimpleNode *> directCalls;
36  rvsdg::GraphExport * rvsdgExport = nullptr;
37  std::vector<rvsdg::Input *> otherUsers;
38 
39  while (!worklist.empty())
40  {
41  auto input = worklist.front();
42  worklist.pop_front();
43 
44  if (auto lambdaNode = rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(*input))
45  {
46  auto & argument = *lambdaNode->MapInputContextVar(*input).inner;
47  AddToWorklist(worklist, argument);
48  continue;
49  }
50 
51  if (rvsdg::TryGetRegionParentNode<rvsdg::LambdaNode>(*input))
52  {
53  otherUsers.emplace_back(input);
54  continue;
55  }
56 
57  if (auto gammaNode = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(*input))
58  {
59  auto rolevar = gammaNode->MapInput(*input);
60  if (auto entryvar = std::get_if<rvsdg::GammaNode::EntryVar>(&rolevar))
61  {
62  for (auto & argument : entryvar->branchArgument)
63  {
64  AddToWorklist(worklist, *argument);
65  }
66  }
67  continue;
68  }
69 
70  if (auto gamma = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(*input))
71  {
72  auto output = gamma->MapBranchResultExitVar(*input).output;
73  AddToWorklist(worklist, *output);
74  continue;
75  }
76 
77  if (auto theta = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(*input))
78  {
79  auto loopvar = theta->MapInputLoopVar(*input);
80  AddToWorklist(worklist, *loopvar.pre);
81  continue;
82  }
83 
84  if (auto theta = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(*input))
85  {
86  auto loopvar = theta->MapPostLoopVar(*input);
87  AddToWorklist(worklist, *loopvar.output);
88  continue;
89  }
90 
91  if (auto phi = rvsdg::TryGetOwnerNode<rvsdg::PhiNode>(*input))
92  {
93  auto ctxvar = phi->MapInputContextVar(*input);
94  AddToWorklist(worklist, *ctxvar.inner);
95  continue;
96  }
97 
98  if (auto phi = rvsdg::TryGetRegionParentNode<rvsdg::PhiNode>(*input))
99  {
100  auto fixvar = phi->MapResultFixVar(*input);
101  AddToWorklist(worklist, *fixvar.recref);
102 
103  auto output = fixvar.output;
104  AddToWorklist(worklist, *output);
105  continue;
106  }
107 
108  if (auto deltaNode = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(*input))
109  {
110  auto ctxVar = deltaNode->MapInputContextVar(*input);
111  AddToWorklist(worklist, *ctxVar.inner);
112  continue;
113  }
114 
115  if (rvsdg::TryGetRegionParentNode<rvsdg::DeltaNode>(*input))
116  {
117  otherUsers.emplace_back(input);
118  continue;
119  }
120 
121  auto inputNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*input);
122  if (is<CallOperation>(inputNode) && input == inputNode->input(0))
123  {
124  directCalls.emplace_back(inputNode);
125  continue;
126  }
127 
128  if (auto graphExport = dynamic_cast<rvsdg::GraphExport *>(input))
129  {
130  rvsdgExport = graphExport;
131  continue;
132  }
133 
134  if (rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*input))
135  {
136  otherUsers.emplace_back(input);
137  continue;
138  }
139 
140  JLM_UNREACHABLE("This should have never happened!");
141  }
142 
143  return CallSummary{ rvsdgExport, std::move(directCalls), std::move(otherUsers) };
144 }
145 
146 }
Lambda node.
Definition: lambda.hpp:83
ContextVar MapInputContextVar(const rvsdg::Input &input) const noexcept
Maps input to context variable.
Definition: lambda.cpp:80
rvsdg::Output * output() const noexcept
Definition: lambda.cpp:176
UsersRange Users()
Definition: node.hpp:354
#define JLM_UNREACHABLE(msg)
Definition: common.hpp:43
Global memory state passed between functions.
static void AddToWorklist(std::deque< rvsdg::Input * > &worklist, rvsdg::Output &output)
Definition: CallSummary.cpp:21
CallSummary ComputeCallSummary(const rvsdg::LambdaNode &lambdaNode)
Definition: CallSummary.cpp:30
rvsdg::Output * inner
Access to bound object in subregion.
Definition: lambda.hpp:117