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  : pointsToGraph_(pointsToGraph)
12 {}
13 
15 
16 std::string
18 {
19  return "PointsToGraphAA";
20 }
21 
24  const rvsdg::Output & p1,
25  const size_t s1,
26  const rvsdg::Output & p2,
27  const size_t s2)
28 {
29  // If the two pointers are the same value, they must alias
30  if (&p1 == &p2)
31  return MustAlias;
32 
33  // Assume that all pointers actually exist in the PointsToGraph
34  const auto p1RegisterNode = pointsToGraph_.getNodeForRegister(p1);
35  const auto p2RegisterNode = pointsToGraph_.getNodeForRegister(p2);
36 
37  // Check if both pointers may target the external node, to avoid iterating over large sets
38  const bool p1TargetsExternal = pointsToGraph_.isTargetingAllExternallyAvailable(p1RegisterNode);
39  const bool p2TargetsExternal = pointsToGraph_.isTargetingAllExternallyAvailable(p2RegisterNode);
40  if (p1TargetsExternal && p2TargetsExternal)
41  return MayAlias;
42 
43  // If both p1 and p2 have exactly one possible target, which is the same for both,
44  // and is the same size as the operations, and only represents one concrete memory location,
45  // we can respond with MustAlias
46  if (s1 == s2)
47  {
48  const auto p1SingleTarget = TryGetSingleTarget(p1RegisterNode, s1);
49  const auto p2SingleTarget = TryGetSingleTarget(p2RegisterNode, s2);
50  if (p1SingleTarget.has_value() && p2SingleTarget.has_value()
51  && *p1SingleTarget == *p2SingleTarget && IsRepresentingSingleMemoryLocation(*p1SingleTarget)
52  && pointsToGraph_.tryGetNodeSize(*p1SingleTarget) == s1)
53  {
54  return MustAlias;
55  }
56  }
57 
58  // For a memory location to be the target of both p1 and p2, it needs to be large enough
59  // to represent both [p1, p1+s1) and [p2, p2+s2)
60  const auto neededSize = std::max(s1, s2);
61 
62  // At least one of the nodes only has explicit targets
63  PointsToGraph::NodeIndex onlyExplicitTargetsNode = p1RegisterNode;
64  PointsToGraph::NodeIndex otherNode = p2RegisterNode;
65  if (p1TargetsExternal)
66  {
67  JLM_ASSERT(!p2TargetsExternal);
68  std::swap(onlyExplicitTargetsNode, otherNode);
69  }
70 
71  for (const auto target : pointsToGraph_.getExplicitTargets(onlyExplicitTargetsNode).Items())
72  {
73  // Skip memory locations that are too small
74  const auto targetSize = pointsToGraph_.tryGetNodeSize(target);
75 
76  if (targetSize.has_value() && *targetSize < neededSize)
77  continue;
78 
79  if (pointsToGraph_.isTargeting(otherNode, target))
80  return MayAlias;
81  }
82 
83  return NoAlias;
84 }
85 
86 std::optional<PointsToGraph::NodeIndex>
88 {
89  // Nodes that target everything external always have "infinite" targets
91  return std::nullopt;
92 
93  std::optional<PointsToGraph::NodeIndex> singleTarget = std::nullopt;
94 
95  for (const auto target : pointsToGraph_.getExplicitTargets(node).Items())
96  {
97  // Skip memory locations that are too small to hold size
98  const auto targetSize = pointsToGraph_.tryGetNodeSize(target);
99  if (targetSize.has_value() && *targetSize < size)
100  continue;
101 
102  // If we already have a "single target", there is more than one target
103  if (singleTarget.has_value())
104  return std::nullopt;
105 
106  singleTarget = target;
107  }
108 
109  return singleTarget;
110 }
111 
112 bool
114 {
115  switch (pointsToGraph_.getNodeKind(node))
116  {
120  return false;
124  return true;
125  default:
126  throw std::logic_error("Unknown node kind");
127  }
128 }
129 
130 }
bool IsRepresentingSingleMemoryLocation(PointsToGraph::NodeIndex node) const
std::optional< PointsToGraph::NodeIndex > TryGetSingleTarget(PointsToGraph::NodeIndex node, size_t size) const
PointsToGraphAliasAnalysis(const PointsToGraph &pointsToGraph)
~PointsToGraphAliasAnalysis() noexcept override
AliasQueryResponse Query(const rvsdg::Output &p1, size_t s1, const rvsdg::Output &p2, size_t s2) override
std::optional< size_t > tryGetNodeSize(NodeIndex index) const noexcept
bool isTargeting(NodeIndex source, NodeIndex target) const
const util::HashSet< NodeIndex > & getExplicitTargets(NodeIndex index) const
NodeIndex getNodeForRegister(const rvsdg::Output &output) const
bool isTargetingAllExternallyAvailable(NodeIndex index) const
NodeKind getNodeKind(NodeIndex index) const
#define JLM_ASSERT(x)
Definition: common.hpp:16
static std::string ToString(const std::vector< MemoryNodeId > &memoryNodeIds)