Jlm
AgnosticModRefSummarizer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 Nico Reißmann <nico.reissmann@gmail.com>
3  * Copyright 2025 Håvard Krogstie <krogstie.havard@gmail.com>
4  * See COPYING for terms of redistribution.
5  */
6 
15 #include <jlm/rvsdg/MatchType.hpp>
16 
17 namespace jlm::llvm::aa
18 {
19 
24 {
25 public:
27  std::unordered_map<const rvsdg::SimpleNode *, util::HashSet<PointsToGraph::NodeIndex>>;
28 
29  ~AgnosticModRefSummary() noexcept override = default;
30 
31 private:
33  const PointsToGraph & pointsToGraph,
34  util::HashSet<PointsToGraph::NodeIndex> allMemoryNodes)
35  : PointsToGraph_(pointsToGraph),
36  AllMemoryNodes_(std::move(allMemoryNodes))
37  {}
38 
39 public:
41 
43 
45  operator=(const AgnosticModRefSummary &) = delete;
46 
49 
50  [[nodiscard]] const PointsToGraph &
51  GetPointsToGraph() const noexcept override
52  {
53  return PointsToGraph_;
54  }
55 
56  void
58  const rvsdg::SimpleNode & node,
60  {
61  JLM_ASSERT(SimpleNodeModRefs_.find(&node) == SimpleNodeModRefs_.end());
62  SimpleNodeModRefs_[&node] = std::move(modRefSet);
63  }
64 
65  [[nodiscard]] const util::HashSet<PointsToGraph::NodeIndex> &
66  GetSimpleNodeModRef(const rvsdg::SimpleNode & node) const override
67  {
68  if (const auto it = SimpleNodeModRefs_.find(&node); it != SimpleNodeModRefs_.end())
69  {
70  return it->second;
71  }
72  if (is<CallOperation>(node.GetOperation()))
73  {
74  return AllMemoryNodes_;
75  }
76  throw std::logic_error("Unhandled node type.");
77  }
78 
79  [[nodiscard]] const util::HashSet<PointsToGraph::NodeIndex> &
80  GetGammaEntryModRef([[maybe_unused]] const rvsdg::GammaNode & gamma) const override
81  {
82  return AllMemoryNodes_;
83  }
84 
85  [[nodiscard]] const util::HashSet<PointsToGraph::NodeIndex> &
86  GetGammaExitModRef([[maybe_unused]] const rvsdg::GammaNode & gamma) const override
87  {
88  return AllMemoryNodes_;
89  }
90 
91  [[nodiscard]] const util::HashSet<PointsToGraph::NodeIndex> &
92  GetThetaModRef([[maybe_unused]] const rvsdg::ThetaNode & theta) const override
93  {
94  return AllMemoryNodes_;
95  }
96 
97  [[nodiscard]] const util::HashSet<PointsToGraph::NodeIndex> &
98  GetLambdaEntryModRef([[maybe_unused]] const rvsdg::LambdaNode & lambda) const override
99  {
100  return AllMemoryNodes_;
101  }
102 
103  [[nodiscard]] const util::HashSet<PointsToGraph::NodeIndex> &
104  GetLambdaExitModRef([[maybe_unused]] const rvsdg::LambdaNode & lambda) const override
105  {
106  return AllMemoryNodes_;
107  }
108 
109  static std::unique_ptr<AgnosticModRefSummary>
111  {
112  return std::unique_ptr<AgnosticModRefSummary>(
113  new AgnosticModRefSummary(pointsToGraph, std::move(memoryNodes)));
114  }
115 
116 private:
120 };
121 
123 
125 
126 std::unique_ptr<ModRefSummary>
128  const rvsdg::RvsdgModule & rvsdgModule,
129  const PointsToGraph & pointsToGraph,
131 {
132  auto statistics =
133  Statistics::Create(rvsdgModule.SourceFilePath().value(), statisticsCollector, pointsToGraph);
134  statistics->StartCollecting();
135 
136  auto allMemoryNodes = GetAllMemoryNodes(pointsToGraph);
137 
138  ModRefSummary_ = AgnosticModRefSummary::Create(pointsToGraph, std::move(allMemoryNodes));
139 
140  // Create ModRefSets for SimpleNodes that affect memory
141  AnnotateRegion(rvsdgModule.Rvsdg().GetRootRegion());
142 
143  statistics->StopCollecting();
144  statisticsCollector.CollectDemandedStatistics(std::move(statistics));
145 
146  return std::move(ModRefSummary_);
147 }
148 
151 {
153  for (const auto allocaNode : pointsToGraph.allocaNodes())
154  memoryNodes.insert(allocaNode);
155 
156  for (const auto deltaNode : pointsToGraph.deltaNodes())
157  memoryNodes.insert(deltaNode);
158 
159  for (const auto lambdaNode : pointsToGraph.lambdaNodes())
160  memoryNodes.insert(lambdaNode);
161 
162  for (const auto mallocNode : pointsToGraph.mallocNodes())
163  memoryNodes.insert(mallocNode);
164 
165  for (const auto importNode : pointsToGraph.importNodes())
166  memoryNodes.insert(importNode);
167 
168  memoryNodes.insert(pointsToGraph.getExternalMemoryNode());
169 
170  JLM_ASSERT(memoryNodes.Size() == pointsToGraph.numMemoryNodes());
171 
172  return memoryNodes;
173 }
174 
175 void
177 {
178  for (const auto & node : region.Nodes())
179  {
181  node,
182  [&](const rvsdg::SimpleNode & simpleNode)
183  {
184  AnnotateSimpleNode(simpleNode);
185  },
186  [&](const rvsdg::StructuralNode & structuralNode)
187  {
188  for (const auto & subregion : structuralNode.Subregions())
189  {
190  AnnotateRegion(subregion);
191  }
192  });
193  }
194 }
195 
196 void
198  const rvsdg::Output & output,
199  util::HashSet<PointsToGraph::NodeIndex> & modRefSet) const
200 {
201  const auto & pointsToGraph = ModRefSummary_->GetPointsToGraph();
203  const auto & addressReg = pointsToGraph.getNodeForRegister(output);
204  for (const auto target : pointsToGraph.getExplicitTargets(addressReg).Items())
205  {
206  modRefSet.insert(target);
207  }
208  if (pointsToGraph.isTargetingAllExternallyAvailable(addressReg))
209  {
210  for (const auto implicitTarget : pointsToGraph.getExternallyAvailableNodes())
211  {
212  modRefSet.insert(implicitTarget);
213  }
214  }
215 }
216 
217 void
219 {
221  node.GetOperation(),
222  [&](const StoreOperation &)
223  {
224  const auto & address = *StoreOperation::AddressInput(node).origin();
225  util::HashSet<PointsToGraph::NodeIndex> modRefSet;
226  AddPointerTargetsToModRefSet(address, modRefSet);
227  ModRefSummary_->SetSimpleNodeModRef(node, std::move(modRefSet));
228  },
229  [&](const LoadOperation &)
230  {
231  const auto & address = *LoadOperation::AddressInput(node).origin();
232  util::HashSet<PointsToGraph::NodeIndex> modRefSet;
233  AddPointerTargetsToModRefSet(address, modRefSet);
234  ModRefSummary_->SetSimpleNodeModRef(node, std::move(modRefSet));
235  },
236  [&](const MemCpyOperation &)
237  {
238  util::HashSet<PointsToGraph::NodeIndex> modRefSet;
239  const auto & srcAddress = *MemCpyOperation::sourceInput(node).origin();
240  const auto & dstAddress = *MemCpyOperation::destinationInput(node).origin();
241  AddPointerTargetsToModRefSet(srcAddress, modRefSet);
242  AddPointerTargetsToModRefSet(dstAddress, modRefSet);
243  ModRefSummary_->SetSimpleNodeModRef(node, std::move(modRefSet));
244  },
245  [&](const MemSetOperation &)
246  {
247  util::HashSet<PointsToGraph::NodeIndex> modRefSet;
248  const auto & dstAddress = *MemSetOperation::destinationInput(node).origin();
249  AddPointerTargetsToModRefSet(dstAddress, modRefSet);
250  ModRefSummary_->SetSimpleNodeModRef(node, std::move(modRefSet));
251  },
252  [&](const FreeOperation &)
253  {
254  util::HashSet<PointsToGraph::NodeIndex> modRefSet;
255  const auto & freeAddress = *FreeOperation::addressInput(node).origin();
256  AddPointerTargetsToModRefSet(freeAddress, modRefSet);
257  ModRefSummary_->SetSimpleNodeModRef(node, std::move(modRefSet));
258  },
259  [&](const AllocaOperation &)
260  {
261  const auto allocaMemoryNode = ModRefSummary_->GetPointsToGraph().getNodeForAlloca(node);
262  ModRefSummary_->SetSimpleNodeModRef(node, { allocaMemoryNode });
263  },
264  [&](const MallocOperation &)
265  {
266  const auto mallocMemoryNode = ModRefSummary_->GetPointsToGraph().getNodeForMalloc(node);
267  ModRefSummary_->SetSimpleNodeModRef(node, { mallocMemoryNode });
268  },
269  [&](const CallOperation &)
270  {
271  // CallOperations are omitted on purpose, as calls use the AllMemoryNodes as their ModRef
272  // set.
273  },
274  [&](const MemoryStateOperation &)
275  {
276  // Memory state operations are only used to route memory state edges
277  },
278  [&]()
279  {
280  // Any remaining type of node should not involve any memory states
281  JLM_ASSERT(!hasMemoryState(node));
282  });
283 }
284 
285 std::unique_ptr<ModRefSummary>
286 AgnosticModRefSummarizer::Create(
287  const rvsdg::RvsdgModule & rvsdgModule,
288  const PointsToGraph & pointsToGraph,
290 {
291  AgnosticModRefSummarizer summarizer;
292  return summarizer.SummarizeModRefs(rvsdgModule, pointsToGraph, statisticsCollector);
293 }
294 
295 std::unique_ptr<ModRefSummary>
296 AgnosticModRefSummarizer::Create(
297  const rvsdg::RvsdgModule & rvsdgModule,
298  const PointsToGraph & pointsToGraph)
299 {
301  return Create(rvsdgModule, pointsToGraph, statisticsCollector);
302 }
303 
304 }
static jlm::util::StatisticsCollector statisticsCollector
static std::unique_ptr< Statistics > Create(const util::FilePath &sourceFile, const util::StatisticsCollector &statisticsCollector, const PointsToGraph &pointsToGraph)
std::unique_ptr< ModRefSummary > SummarizeModRefs(const rvsdg::RvsdgModule &rvsdgModule, const PointsToGraph &pointsToGraph, util::StatisticsCollector &statisticsCollector) override
void AddPointerTargetsToModRefSet(const rvsdg::Output &output, util::HashSet< PointsToGraph::NodeIndex > &modRefSet) const
static util::HashSet< PointsToGraph::NodeIndex > GetAllMemoryNodes(const PointsToGraph &pointsToGraph)
void AnnotateRegion(const rvsdg::Region &region)
void AnnotateSimpleNode(const rvsdg::SimpleNode &node)
std::unique_ptr< AgnosticModRefSummary > ModRefSummary_
Mod/Ref summary of agnostic mod/ref summarizer.
AgnosticModRefSummary(AgnosticModRefSummary &&)=delete
const util::HashSet< PointsToGraph::NodeIndex > & GetSimpleNodeModRef(const rvsdg::SimpleNode &node) const override
void SetSimpleNodeModRef(const rvsdg::SimpleNode &node, util::HashSet< PointsToGraph::NodeIndex > modRefSet)
const util::HashSet< PointsToGraph::NodeIndex > & GetGammaExitModRef([[maybe_unused]] const rvsdg::GammaNode &gamma) const override
std::unordered_map< const rvsdg::SimpleNode *, util::HashSet< PointsToGraph::NodeIndex > > SimpleNodeModRefMap
~AgnosticModRefSummary() noexcept override=default
const util::HashSet< PointsToGraph::NodeIndex > & GetGammaEntryModRef([[maybe_unused]] const rvsdg::GammaNode &gamma) const override
AgnosticModRefSummary & operator=(const AgnosticModRefSummary &)=delete
const util::HashSet< PointsToGraph::NodeIndex > & GetLambdaExitModRef([[maybe_unused]] const rvsdg::LambdaNode &lambda) const override
static std::unique_ptr< AgnosticModRefSummary > Create(const PointsToGraph &pointsToGraph, util::HashSet< PointsToGraph::NodeIndex > memoryNodes)
const util::HashSet< PointsToGraph::NodeIndex > & GetThetaModRef([[maybe_unused]] const rvsdg::ThetaNode &theta) const override
AgnosticModRefSummary(const AgnosticModRefSummary &)=delete
AgnosticModRefSummary(const PointsToGraph &pointsToGraph, util::HashSet< PointsToGraph::NodeIndex > allMemoryNodes)
AgnosticModRefSummary & operator=(AgnosticModRefSummary &&)=delete
const util::HashSet< PointsToGraph::NodeIndex > & GetLambdaEntryModRef([[maybe_unused]] const rvsdg::LambdaNode &lambda) const override
util::HashSet< PointsToGraph::NodeIndex > AllMemoryNodes_
const PointsToGraph & GetPointsToGraph() const noexcept override
size_t numMemoryNodes() const noexcept
AllocaNodeRange allocaNodes() const noexcept
NodeIndex getExternalMemoryNode() const noexcept
LambdaNodeRange lambdaNodes() const noexcept
DeltaNodeRange deltaNodes() const noexcept
MallocNodeRange mallocNodes() const noexcept
ImportNodeRange importNodes() const noexcept
Conditional operator / pattern matching.
Definition: gamma.hpp:99
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
Lambda node.
Definition: lambda.hpp:83
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
NodeRange Nodes() noexcept
Definition: region.hpp:328
const std::optional< util::FilePath > & SourceFilePath() const noexcept
Definition: RvsdgModule.hpp:73
Graph & Rvsdg() noexcept
Definition: RvsdgModule.hpp:57
const SimpleOperation & GetOperation() const noexcept override
Definition: simple-node.cpp:48
bool insert(ItemType item)
Definition: HashSet.hpp:210
std::size_t Size() const noexcept
Definition: HashSet.hpp:187
void CollectDemandedStatistics(std::unique_ptr< Statistics > statistics)
Definition: Statistics.hpp:574
#define JLM_ASSERT(x)
Definition: common.hpp:16
bool IsPointerCompatible(const rvsdg::Output &value)
bool hasMemoryState(const rvsdg::Node &node)
void MatchTypeWithDefault(T &obj, const Fns &... fns)
Pattern match over subclass type of given object with default handler.
void MatchTypeOrFail(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.