Jlm
Loading...
Searching...
No Matches
LazyCycleDetection.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2024 HÃ¥vard Krogstie <krogstie.havard@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#ifndef JLM_LLVM_OPT_ALIAS_ANALYSES_LAZYCYCLEDETECTION_HPP
7#define JLM_LLVM_OPT_ALIAS_ANALYSES_LAZYCYCLEDETECTION_HPP
8
10#include <jlm/util/HashSet.hpp>
11
12#include <limits>
13#include <optional>
14#include <stack>
15#include <vector>
16
17namespace jlm::llvm::aa
18{
19
26template<typename GetSuccessorsFunctor, typename UnifyPointerObjectsFunctor>
28{
29
30public:
32 PointerObjectSet & set,
33 const GetSuccessorsFunctor & GetSuccessors,
34 const UnifyPointerObjectsFunctor & unifyPointerObjects)
35 : Set_(set),
36 GetSuccessors_(GetSuccessors),
37 UnifyPointerObjects_(unifyPointerObjects)
38 {}
39
43 void
48
49 bool
50 IsInitialized() const noexcept
51 {
52 return NodeStates_.size() == Set_.NumPointerObjects();
53 }
54
63 std::optional<PointerObjectIndex>
65 {
69
70 // Add this edge to the list of checked edges, or return if it was already there
71 if (!CheckedEdges_.insert({ subset, superset }))
72 return std::nullopt;
73
75
76 JLM_ASSERT(DfsStack_.empty());
77 DfsStack_.push(superset);
78
79 // Reset all node states
80 std::fill(NodeStates_.begin(), NodeStates_.end(), NodeStateNotVisited);
81
82 while (!DfsStack_.empty())
83 {
84 auto node = DfsStack_.top();
86 {
88 // Make sure all successors get visited
89 for (auto successor : GetSuccessors_(node))
90 {
91 auto successorRoot = Set_.GetUnificationRoot(successor);
92
93 // Cycle found! Do not add the subset to the dfs stack
94 if (successorRoot == subset)
95 continue;
96
97 if (NodeStates_[successorRoot] != NodeStateNotVisited)
98 continue;
99
100 DfsStack_.push(successorRoot);
101 }
102 }
103 else if (NodeStates_[node] == NodeStateVisited)
104 {
105 DfsStack_.pop();
107
108 // Check if any successors are unified with the subset. If so, join it!
109 for (auto successor : GetSuccessors_(node))
110 {
111 auto successorRoot = Set_.GetUnificationRoot(successor);
112 if (successorRoot == subset)
113 {
114 subset = UnifyPointerObjects_(node, subset);
116 break;
117 }
118 }
119 }
120 else
121 {
122 // The node has already been visited for a second time
123 DfsStack_.pop();
124 }
125 }
126
128 superset = Set_.GetUnificationRoot(superset);
129 if (subset == superset)
130 {
132 return subset;
133 }
134 return std::nullopt;
135 }
136
140 [[nodiscard]] size_t
142 {
144 }
145
149 [[nodiscard]] size_t
150 NumCyclesDetected() const noexcept
151 {
152 return NumCyclesDetected_;
153 }
154
158 [[nodiscard]] size_t
159 NumCycleUnifications() const noexcept
160 {
162 }
163
164private:
166 const GetSuccessorsFunctor & GetSuccessors_;
167 const UnifyPointerObjectsFunctor & UnifyPointerObjects_;
168
169 // A set of all checked simple edges first -> second, to avoid checking again
171
172 // The dfs stack, which may contain the same node multiple times
173 std::stack<PointerObjectIndex> DfsStack_;
174 // Possible states of nodes during the DFS
175 static constexpr uint8_t NodeStateNotVisited = 0;
176 static constexpr uint8_t NodeStateVisited = 1;
177 static constexpr uint8_t NodeStatePopped = 2;
178 std::vector<uint8_t> NodeStates_;
179
183};
184
185}
186
187#endif // JLM_LLVM_OPT_ALIAS_ANALYSES_LAZYCYCLEDETECTION_HPP
const UnifyPointerObjectsFunctor & UnifyPointerObjects_
size_t NumCycleUnifications() const noexcept
static constexpr uint8_t NodeStateNotVisited
size_t NumCyclesDetected() const noexcept
static constexpr uint8_t NodeStateVisited
util::HashSet< std::pair< PointerObjectIndex, PointerObjectIndex > > CheckedEdges_
size_t NumCycleDetectionAttempts() const noexcept
std::stack< PointerObjectIndex > DfsStack_
const GetSuccessorsFunctor & GetSuccessors_
LazyCycleDetector(PointerObjectSet &set, const GetSuccessorsFunctor &GetSuccessors, const UnifyPointerObjectsFunctor &unifyPointerObjects)
static constexpr uint8_t NodeStatePopped
std::optional< PointerObjectIndex > OnPropagatedNothing(PointerObjectIndex subset, PointerObjectIndex superset)
PointerObjectIndex GetUnificationRoot(PointerObjectIndex index) const noexcept
bool IsUnificationRoot(PointerObjectIndex index) const noexcept
size_t NumPointerObjects() const noexcept
bool insert(ItemType item)
Definition HashSet.hpp:210
#define JLM_ASSERT(x)
Definition common.hpp:16
uint32_t PointerObjectIndex