Jlm
PointsToGraphAliasAnalysis.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2025 HÃ¥vard Krogstie <krogstie.havard@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
7 
8 namespace jlm::llvm::aa
9 {
11  std::shared_ptr<const PointsToGraph> pointsToGraph)
12  : pointsToGraph_(std::move(pointsToGraph))
13 {}
14 
16 
17 std::string
19 {
20  return "PointsToGraphAA";
21 }
22 
25  const rvsdg::Output & p1,
26  const size_t s1,
27  const rvsdg::Output & p2,
28  const size_t s2)
29 {
30  // If the two pointers are the same value, they must alias
31  if (&p1 == &p2)
32  return MustAlias;
33 
34  // The output may have been created after the PointsToGraph
35  // In which case we have no better response than MayAlias
36  auto tryP1RegisterNode = pointsToGraph_->tryGetNodeForRegister(p1);
37  if (!tryP1RegisterNode)
38  return MayAlias;
39 
40  auto tryP2RegisterNode = pointsToGraph_->tryGetNodeForRegister(p2);
41  if (!tryP2RegisterNode)
42  return MayAlias;
43 
44  const auto p1RegisterNode = *tryP1RegisterNode;
45  const auto p2RegisterNode = *tryP2RegisterNode;
46 
47  // Check if both pointers may target the external node, to avoid iterating over large sets
48  const bool p1TargetsExternal = pointsToGraph_->isTargetingAllExternallyAvailable(p1RegisterNode);
49  const bool p2TargetsExternal = pointsToGraph_->isTargetingAllExternallyAvailable(p2RegisterNode);
50  if (p1TargetsExternal && p2TargetsExternal)
51  return MayAlias;
52 
53  // If both p1 and p2 have exactly one possible target, which is the same for both,
54  // and is the same size as the operations, and only represents one concrete memory location,
55  // we can respond with MustAlias
56  if (s1 == s2)
57  {
58  const auto p1SingleTarget = TryGetSingleTarget(p1RegisterNode, s1);
59  const auto p2SingleTarget = TryGetSingleTarget(p2RegisterNode, s2);
60  if (p1SingleTarget.has_value() && p2SingleTarget.has_value()
61  && *p1SingleTarget == *p2SingleTarget && IsRepresentingSingleMemoryLocation(*p1SingleTarget)
62  && pointsToGraph_->tryGetNodeSize(*p1SingleTarget) == s1)
63  {
64  return MustAlias;
65  }
66  }
67 
68  // For a memory location to be the target of both p1 and p2, it needs to be large enough
69  // to represent both [p1, p1+s1) and [p2, p2+s2)
70  const auto neededSize = std::max(s1, s2);
71 
72  // At least one of the nodes only has explicit targets
73  PointsToGraph::NodeIndex onlyExplicitTargetsNode = p1RegisterNode;
74  PointsToGraph::NodeIndex otherNode = p2RegisterNode;
75  if (p1TargetsExternal)
76  {
77  JLM_ASSERT(!p2TargetsExternal);
78  std::swap(onlyExplicitTargetsNode, otherNode);
79  }
80 
81  for (const auto target : pointsToGraph_->getExplicitTargets(onlyExplicitTargetsNode).Items())
82  {
83  // Skip memory locations that are too small
84  const auto targetSize = pointsToGraph_->tryGetNodeSize(target);
85 
86  if (targetSize.has_value() && *targetSize < neededSize)
87  continue;
88 
89  if (pointsToGraph_->isTargeting(otherNode, target))
90  return MayAlias;
91  }
92 
93  return NoAlias;
94 }
95 
96 std::optional<PointsToGraph::NodeIndex>
98 {
99  // Nodes that target everything external always have "infinite" targets
100  if (pointsToGraph_->isTargetingAllExternallyAvailable(node))
101  return std::nullopt;
102 
103  std::optional<PointsToGraph::NodeIndex> singleTarget = std::nullopt;
104 
105  for (const auto target : pointsToGraph_->getExplicitTargets(node).Items())
106  {
107  // Skip memory locations that are too small to hold size
108  const auto targetSize = pointsToGraph_->tryGetNodeSize(target);
109  if (targetSize.has_value() && *targetSize < size)
110  continue;
111 
112  // If we already have a "single target", there is more than one target
113  if (singleTarget.has_value())
114  return std::nullopt;
115 
116  singleTarget = target;
117  }
118 
119  return singleTarget;
120 }
121 
122 bool
124 {
125  switch (pointsToGraph_->getNodeKind(node))
126  {
130  return false;
134  return true;
135  default:
136  throw std::logic_error("Unknown node kind");
137  }
138 }
139 
140 }
PointsToGraphAliasAnalysis(std::shared_ptr< const PointsToGraph > pointsToGraph)
bool IsRepresentingSingleMemoryLocation(PointsToGraph::NodeIndex node) const
std::optional< PointsToGraph::NodeIndex > TryGetSingleTarget(PointsToGraph::NodeIndex node, size_t size) const
std::shared_ptr< const PointsToGraph > pointsToGraph_
~PointsToGraphAliasAnalysis() noexcept override
AliasQueryResponse Query(const rvsdg::Output &p1, size_t s1, const rvsdg::Output &p2, size_t s2) override
#define JLM_ASSERT(x)
Definition: common.hpp:16
static std::string ToString(const std::vector< MemoryNodeId > &memoryNodeIds)