12 #ifndef NOM_GRAPH_ALGORITHMS_H 13 #define NOM_GRAPH_ALGORITHMS_H 15 #include "nomnigraph/Graph/Graph.h" 18 #include <unordered_map> 19 #include <unordered_set> 25 template <
typename T,
typename U>
26 std::vector<Subgraph<T, U>> tarjans(Graph<T, U> *g);
27 #include "nomnigraph/Graph/TarjansImpl.h" 31 void reachable(
typename G::NodeRef root,
typename G::NodeRef ignored,
32 std::unordered_set<typename G::NodeRef> *seen) {
34 for (
const auto &outEdge : root->getOutEdges()) {
35 auto &newNode = outEdge->head();
36 if (newNode != ignored && (seen->find(newNode) == seen->end())) {
37 reachable<G>(newNode, ignored, seen);
61 Graph<typename G::NodeRef, int>
62 dominatorTree(G *g,
typename G::NodeRef source =
nullptr) {
63 assert(g->getMutableNodes().size() > 0 &&
64 "Cannot find dominator tree of empty graph.");
66 auto rootSCC = tarjans(g).back();
67 assert(rootSCC.getNodes().size() == 1 &&
68 "Cannot determine source node topologically, please specify one.");
69 for (
auto &node : rootSCC.getNodes()) {
75 std::unordered_set<typename G::NodeRef> allNodes;
76 Graph<typename G::NodeRef, int> tree;
77 std::unordered_map<
typename G::NodeRef,
78 typename Graph<typename G::NodeRef, int>::NodeRef>
80 std::unordered_map<
typename G::NodeRef,
81 std::unordered_set<typename G::NodeRef>>
84 for (
auto node : g->getMutableNodes()) {
85 mapToTreeNode[node] = tree.createNode(std::move(node));
89 dominatorMap[source].insert(node);
92 for (
const auto &node : g->getMutableNodes()) {
96 std::unordered_set<typename G::NodeRef> seen;
97 std::unordered_set<typename G::NodeRef> dominated;
98 reachable<G>(source, node, &seen);
99 for (
auto testNode : dominatorMap[source]) {
100 if (seen.find(testNode) == seen.end() && testNode != node) {
101 dominated.insert(testNode);
104 dominatorMap[node] = dominated;
107 std::unordered_set<typename G::NodeRef> nextPass;
108 nextPass.insert(source);
110 while (nextPass.size()) {
111 for (
auto parent : nextPass) {
112 for (
auto child : dominatorMap[parent]) {
113 while (mapToTreeNode[child]->getInEdges().size()) {
114 tree.deleteEdge(mapToTreeNode[child]->getInEdges().front());
116 tree.createEdge(mapToTreeNode[parent], mapToTreeNode[child]);
117 if (dominatorMap.find(child) != dominatorMap.end()) {
118 nextPass.insert(child);
121 nextPass.erase(parent);
129 template <
typename G>
130 std::unordered_map<typename G::NodeRef, typename G::NodeRef>
131 immediateDominatorMap(G *g,
typename G::NodeRef source =
nullptr) {
132 std::unordered_map<typename G::NodeRef, typename G::NodeRef> idomMap;
133 auto idomTree = dominatorTree(g, source);
134 for (
auto node : idomTree.getMutableNodes()) {
136 assert(node->getInEdges().size() <= 1 &&
"Invalid dominator tree generated from graph, cannot determing idom map.");
138 if (node->getInEdges().size() == 0) {
139 idomMap[node->data()] = node->data();
141 auto idom = node->getInEdges()[0]->tail();
142 idomMap[node->data()] = idom->data();
152 template <
typename G>
153 std::unordered_map<typename G::NodeRef, std::unordered_set<typename G::NodeRef>>
154 dominanceFrontierMap(G *g,
typename G::NodeRef source =
nullptr) {
155 auto idomMap = immediateDominatorMap(g, source);
156 std::unordered_map<typename G::NodeRef, std::unordered_set<typename G::NodeRef>> domFrontierMap;
157 for (
const auto node : g->getMutableNodes()) {
158 if (node->getInEdges().size() < 2) {
continue; }
159 for (
auto inEdge : node->getInEdges()) {
160 auto predecessor = inEdge->tail();
162 auto runner = predecessor;
163 while (runner != idomMap[node]) {
164 domFrontierMap[runner].insert(node);
165 runner = idomMap[runner];
169 return domFrontierMap;
175 #endif // NOM_GRAPH_ALGORITHMS_H