Skip to content

Commit f40a018

Browse files
author
Roland Leißa
committed
simplify
1 parent 7ede74b commit f40a018

File tree

3 files changed

+126
-116
lines changed

3 files changed

+126
-116
lines changed

include/graphtool/graph.h

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
namespace graphtool {
88

9+
static constexpr auto Not_Visited = size_t(-1);
10+
911
using fe::Sym;
1012

1113
class Graph {
@@ -15,35 +17,18 @@ class Graph {
1517

1618
class Node {
1719
private:
18-
static constexpr auto Not_Visited = size_t(-1);
19-
2020
Node(Sym name)
2121
: name_(name) {}
2222

2323
public:
2424
Sym name() const { return name_; }
25-
template<size_t mode> std::string dot() const;
26-
template<size_t mode> size_t pre() const { return order_[mode].pre; }
27-
template<size_t mode> size_t post() const { return order_[mode].post; }
28-
template<size_t mode> size_t rp() const { return order_[mode].rp; }
29-
template<size_t mode> Node* idom() const { return idom_[mode]; }
30-
template<size_t mode> Node*& idom() { return idom_[mode]; }
31-
template<size_t mode> const auto& children() const { return children_[mode]; }
32-
template<size_t mode> auto& children() { return children_[mode]; }
33-
template<size_t mode> const auto& frontier() const { return frontier_[mode]; }
34-
template<size_t mode> auto& frontier() { return frontier_[mode]; }
3525

3626
void link(Node* succ) {
3727
this->succs_.emplace(succ);
3828
succ->preds_.emplace(this);
3929
}
4030

41-
template<size_t mode> const auto& preds() const { return mode == 0 ? preds_ : succs_; }
42-
template<size_t mode> const auto& succs() const { return mode == 0 ? succs_ : preds_; }
43-
4431
private:
45-
template<size_t> std::pair<size_t, size_t> number(size_t, size_t);
46-
4732
Sym name_;
4833
NodeSet preds_, succs_;
4934

@@ -59,6 +44,7 @@ class Graph {
5944
std::array<NodeSet, 2> frontier_;
6045

6146
friend class Graph;
47+
template<size_t M> friend class BiGraph;
6248
};
6349

6450
Graph(const Graph&) = delete;
@@ -80,22 +66,11 @@ class Graph {
8066
fe::Driver& driver() { return driver_; }
8167
Sym name() const { return name_; }
8268
const auto& nodes() const { return nodes_; }
83-
template<size_t mode> Node* entry() const { return mode == 0 ? entry_ : exit_; }
84-
template<size_t mode> Node* exit() const { return mode == 0 ? exit_ : exit_; }
85-
template<size_t mode> const auto& rpo() const { return rpo_[mode]; }
8669
///@}
8770

8871
void set_name(Sym name) { name_ = name; }
8972
Node* node(Sym name);
9073
void critical_edge_elimination();
91-
void analyse();
92-
93-
/// @name Output
94-
///@{
95-
template<size_t> void dump_cfg(std::ostream&) const;
96-
template<size_t> void dump_dom_tree(std::ostream&) const;
97-
template<size_t> void dump_dom_frontiers(std::ostream&) const;
98-
///@}
9974

10075
friend void swap(Graph& g1, Graph& g2) noexcept {
10176
using std::swap;
@@ -109,17 +84,66 @@ class Graph {
10984
}
11085

11186
private:
112-
template<size_t> void number();
113-
template<size_t> void dom();
114-
template<size_t> void dom_frontiers();
115-
template<size_t> Node* lca(Node*, Node*);
116-
11787
fe::Driver& driver_;
11888
Sym name_;
11989
Node* entry_ = nullptr;
12090
Node* exit_ = nullptr;
12191
fe::SymMap<Node*> nodes_;
12292
std::array<std::vector<Node*>, 2> rpo_;
93+
94+
template<size_t M> friend class BiGraph;
95+
};
96+
97+
template<size_t M>
98+
class BiGraph {
99+
public:
100+
using Node = Graph::Node;
101+
102+
BiGraph(Graph& graph)
103+
: graph_(graph) {
104+
number();
105+
dom();
106+
dom_frontiers();
107+
}
108+
109+
/// @name Node Wrappers
110+
///@{
111+
static std::string dot(Node*);
112+
static auto& order(Node* n) { return n->order_[M]; }
113+
static size_t pre(Node* n) { return order(n).pre; }
114+
static size_t post(Node* n) { return order(n).post; }
115+
static size_t rp(Node* n) { return order(n).rp; }
116+
static Node*& idom(Node* n) { return n->idom_[M]; }
117+
static auto& children(Node* n) { return n->children_[M]; }
118+
static auto& frontier(Node* n) { return n->frontier_[M]; }
119+
static const auto& preds(Node* n) { return M == 0 ? n->preds_ : n->succs_; }
120+
static const auto& succs(Node* n) { return M == 0 ? n->succs_ : n->preds_; }
121+
static std::pair<size_t, size_t> number(Node*, size_t, size_t);
122+
///@}
123+
124+
/// @name Getters
125+
///@{
126+
Sym name() const { return graph_.name(); }
127+
Node* entry() const { return M == 0 ? graph_.entry_ : graph_.exit_; }
128+
Node* exit() const { return M == 0 ? graph_.exit_ : graph_.entry_; }
129+
auto& rpo() { return graph_.rpo_[M]; }
130+
const auto& rpo() const { return graph_.rpo_[M]; }
131+
///@}
132+
133+
/// @name Output
134+
///@{
135+
void dump_cfg(std::ostream&) const;
136+
void dump_dom_tree(std::ostream&) const;
137+
void dump_dom_frontiers(std::ostream&) const;
138+
///@}
139+
140+
private:
141+
void number();
142+
void dom();
143+
void dom_frontiers();
144+
Node* lca(Node*, Node*);
145+
146+
Graph& graph_;
123147
};
124148

125149
} // namespace graphtool

src/graphtool/graph.cpp

Lines changed: 61 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ void Graph::critical_edge_elimination() {
2323
auto x = exit_; // we create new nodes below - so memorize proper exit ...
2424

2525
for (auto [_, node] : nodes_) {
26-
if (node->succs<0>().size() > 1) {
27-
for (auto succ : node->succs<0>()) {
28-
if (succ->preds<0>().size() > 1) crit.emplace_back(node, succ);
26+
if (node->succs_.size() > 1) {
27+
for (auto succ : node->succs_) {
28+
if (succ->preds_.size() > 1) crit.emplace_back(node, succ);
2929
}
3030
}
3131
}
@@ -42,41 +42,31 @@ void Graph::critical_edge_elimination() {
4242
exit_ = x; // ... and restore again
4343
}
4444

45-
void Graph::analyse() {
46-
number<0>();
47-
number<1>();
48-
dom<0>();
49-
dom<1>();
50-
dom_frontiers<0>();
51-
dom_frontiers<1>();
52-
}
53-
5445
/*
5546
* number
5647
*/
5748

58-
template<size_t mode>
59-
void Graph::number() {
60-
auto [n, m] = entry<mode>()->template number<mode>(0, 0);
49+
template<size_t M> void BiGraph<M>::number() {
50+
auto [n, m] = number(entry(), 0, 0);
6151
assert(n == m);
62-
rpo_[mode].resize(n);
63-
for (auto [_, node] : nodes()) {
64-
auto& order = node->order_[mode];
65-
if (order.post != Graph::Node::Not_Visited) {
66-
size_t i = n - order.post - 1;
67-
order.rp = i;
68-
rpo_[mode][i] = node;
52+
rpo().resize(n);
53+
for (auto [_, node] : graph_.nodes()) {
54+
auto& ord = order(node);
55+
if (ord.post != Not_Visited) {
56+
size_t i = n - ord.post - 1;
57+
ord.rp = i;
58+
rpo()[i] = node;
6959
}
7060
}
7161
}
7262

73-
template<size_t mode>
74-
std::pair<size_t, size_t> Graph::Node::number(size_t pre, size_t post) {
75-
auto& order = order_[mode];
76-
if (order.pre == Not_Visited) {
77-
order.pre = pre++;
78-
for (auto succ : succs<mode>()) std::tie(pre, post) = succ->template number<mode>(pre, post);
79-
order.post = post++;
63+
template<size_t M>
64+
std::pair<size_t, size_t> BiGraph<M>::number(Node* n, size_t pre, size_t post) {
65+
auto& ord = order(n);
66+
if (ord.pre == Not_Visited) {
67+
ord.pre = pre++;
68+
for (auto succ : succs(n)) std::tie(pre, post) = number(succ, pre, post);
69+
ord.post = post++;
8070
}
8171
return {pre, post};
8272
}
@@ -86,14 +76,14 @@ std::pair<size_t, size_t> Graph::Node::number(size_t pre, size_t post) {
8676
*/
8777

8878
// Cooper et al, 2001. A Simple, Fast Dominance Algorithm. http://www.cs.rice.edu/~keith/EMBED/dom.pdf
89-
template<size_t mode> void Graph::dom() {
90-
entry<mode>()->template idom<mode>() = entry<mode>();
79+
template<size_t M> void BiGraph<M>::dom() {
80+
idom(entry()) = entry();
9181

9282
// all idoms different from entry are set to their first found dominating pred
93-
for (auto node : rpo<mode>() | std::views::drop(1)) {
94-
for (auto pred : node->template preds<mode>()) {
95-
if (pred->template rp<mode>() < node->template rp<mode>()) {
96-
node->template idom<mode>() = pred;
83+
for (auto n : rpo() | std::views::drop(1)) {
84+
for (auto pred : preds(n)) {
85+
if (rp(pred) < rp(n)) {
86+
idom(n) = pred;
9787
break;
9888
}
9989
}
@@ -102,40 +92,39 @@ template<size_t mode> void Graph::dom() {
10292
for (bool todo = true; todo;) {
10393
todo = false;
10494

105-
for (auto node : rpo<mode>() | std::views::drop(1)) {
95+
for (auto n : rpo() | std::views::drop(1)) {
10696
Node* new_idom = nullptr;
107-
for (auto pred : node->template preds<mode>()) new_idom = new_idom ? lca<mode>(new_idom, pred) : pred;
97+
for (auto pred : preds(n)) new_idom = new_idom ? lca(new_idom, pred) : pred;
10898

10999
assert(new_idom);
110-
if (node->template idom<mode>() != new_idom) {
111-
node->template idom<mode>() = new_idom;
100+
if (idom(n) != new_idom) {
101+
idom(n) = new_idom;
112102
todo = true;
113103
}
114104
}
115105
}
116106

117-
for (auto node : rpo<mode>() | std::views::drop(1))
118-
node->template idom<mode>()->template children<mode>().emplace_back(node);
107+
for (auto n : rpo() | std::views::drop(1)) children(idom(n)).emplace_back(n);
119108
}
120109

121-
template<size_t mode>
122-
Graph::Node* Graph::lca(Node* i, Node* j) {
110+
template<size_t M>
111+
Graph::Node* BiGraph<M>::lca(Node* i, Node* j) {
123112
assert(i && j);
124-
while (i->template rp<mode>() != j->template rp<mode>()) {
125-
while (i->template rp<mode>() < j->template rp<mode>()) j = j->template idom<mode>();
126-
while (j->template rp<mode>() < i->template rp<mode>()) i = i->template idom<mode>();
113+
while (rp(i) != rp(j)) {
114+
while (rp(i) < rp(j)) j = idom(j);
115+
while (rp(j) < rp(i)) i = idom(i);
127116
}
128117
return i;
129118
}
130119

131-
template<size_t mode>
132-
void Graph::dom_frontiers() {
133-
for (auto node : rpo<mode>() | std::views::drop(1)) {
134-
const auto& preds = node->template preds<mode>();
120+
template<size_t M>
121+
void BiGraph<M>::dom_frontiers() {
122+
for (auto n : rpo() | std::views::drop(1)) {
123+
const auto& preds = this->preds(n);
135124
if (preds.size() > 1) {
136-
auto idom = node->template idom<mode>();
125+
auto idom = this->idom(n);
137126
for (auto pred : preds) {
138-
for (auto i = pred; i != idom; i = i->template idom<mode>()) i->template frontier<mode>().emplace(node);
127+
for (auto i = pred; i != idom; i = this->idom(i)) frontier(i).emplace(n);
139128
}
140129
}
141130
}
@@ -145,42 +134,42 @@ void Graph::dom_frontiers() {
145134
* output
146135
*/
147136

148-
template<size_t mode>
149-
std::string Graph::Node::dot() const {
150-
return std::format("\"{}\\n[{}|{}|{}]\"", name(), pre<mode>(), post<mode>(), rp<mode>());
137+
template<size_t M>
138+
std::string BiGraph<M>::dot(Node* n) {
139+
return std::format("\"{}\\n[{}|{}|{}]\"", n->name(), pre(n), post(n), rp(n));
151140
}
152141

153-
template<size_t mode>
154-
void Graph::dump_cfg(std::ostream& os) const {
142+
template<size_t M>
143+
void BiGraph<M>::dump_cfg(std::ostream& os) const {
155144
os << std::format("digraph {} {{", name()) << std::endl;
156-
for (const char* sep = ""; auto node : rpo<mode>()) {
157-
for (auto succ : node->template succs<mode>()) {
158-
os << sep << std::format("\t{} -> {}", node->template dot<mode>(), succ->template dot<mode>());
145+
for (const char* sep = ""; auto n : rpo()) {
146+
for (auto succ : succs(n)) {
147+
os << sep << std::format("\t{} -> {}", dot(n), dot(succ));
159148
sep = "\n";
160149
}
161150
}
162151
os << std::endl << '}' << std::endl;
163152
}
164153

165-
template<size_t mode>
166-
void Graph::dump_dom_tree(std::ostream& os) const {
154+
template<size_t M>
155+
void BiGraph<M>::dump_dom_tree(std::ostream& os) const {
167156
os << std::format("digraph {} {{", name()) << std::endl;
168-
for (const char* sep = ""; auto node : rpo<mode>()) {
169-
for (auto child : node->template children<mode>()) {
170-
os << sep << std::format("\t{} -> {}", node->template dot<mode>(), child->template dot<mode>());
157+
for (const char* sep = ""; auto n : rpo()) {
158+
for (auto child : children(n)) {
159+
os << sep << std::format("\t{} -> {}", dot(n), dot(child));
171160
sep = "\n";
172161
}
173162
}
174163
os << std::endl << '}' << std::endl;
175164
}
176165

177-
template<size_t mode>
178-
void Graph::dump_dom_frontiers(std::ostream& os) const {
166+
template<size_t M>
167+
void BiGraph<M>::dump_dom_frontiers(std::ostream& os) const {
179168
os << std::format("digraph {} {{", name()) << std::endl;
180169
os << "\trankdir=\"BT\"" << std::endl;
181-
for (const char* sep = ""; auto node : rpo<mode>()) {
182-
for (auto fron : node->template frontier<mode>()) {
183-
os << sep << std::format("\t{} -> {}", node->template dot<mode>(), fron->template dot<mode>());
170+
for (const char* sep = ""; auto n : rpo()) {
171+
for (auto fron : frontier(n)) {
172+
os << sep << std::format("\t{} -> {}", dot(n), dot(fron));
184173
sep = "\n";
185174
}
186175
}
@@ -189,11 +178,7 @@ void Graph::dump_dom_frontiers(std::ostream& os) const {
189178

190179
// instantiate templates
191180

192-
template void Graph::dump_cfg<0>(std::ostream&) const;
193-
template void Graph::dump_cfg<1>(std::ostream&) const;
194-
template void Graph::dump_dom_tree<0>(std::ostream&) const;
195-
template void Graph::dump_dom_tree<1>(std::ostream&) const;
196-
template void Graph::dump_dom_frontiers<0>(std::ostream&) const;
197-
template void Graph::dump_dom_frontiers<1>(std::ostream&) const;
181+
template class BiGraph<0>;
182+
template class BiGraph<1>;
198183

199184
} // namespace graphtool

0 commit comments

Comments
 (0)