/builds/2mk6rsew/0/parcoach/parcoach/src/include/parcoach/andersen/CycleDetector.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef ANDERSEN_CYCLEDETECTOR_H |
2 | | #define ANDERSEN_CYCLEDETECTOR_H |
3 | | |
4 | | #include "GraphTraits.h" |
5 | | |
6 | | #include "llvm/ADT/DenseMap.h" |
7 | | #include "llvm/ADT/DenseSet.h" |
8 | | #include "llvm/ADT/GraphTraits.h" |
9 | | |
10 | | #include <deque> |
11 | | #include <stack> |
12 | | |
13 | | // An abstract base class that offers the functionality of detecting SCC in a |
14 | | // graph Any concreate class that does cycle detection should inherit from this |
15 | | // class, specifiy the GraphType, and implement all the abstract virtual |
16 | | // functions |
17 | | template <class GraphType> class CycleDetector { |
18 | | public: |
19 | | typedef AndersGraphTraits<GraphType> GraphTraits; |
20 | | typedef typename GraphTraits::NodeType NodeType; |
21 | | typedef typename GraphTraits::NodeIterator node_iterator; |
22 | | typedef typename GraphTraits::ChildIterator child_iterator; |
23 | | |
24 | | private: |
25 | | // The SCC stack |
26 | | std::stack<NodeType const *> sccStack; |
27 | | // Map from NodeIndex to DFS number. Nodes that are not in the map are never |
28 | | // visited |
29 | | llvm::DenseMap<NodeType const *, unsigned> dfsNum; |
30 | | // The "inComponent" array in Nutilla's improved SCC algorithm |
31 | | llvm::DenseSet<NodeType const *> inComponent; |
32 | | // DFS timestamp |
33 | | unsigned timestamp; |
34 | | |
35 | | // visiting each node and perform some task |
36 | 33.0k | void visit(NodeType *node) { |
37 | 33.0k | unsigned myTimeStamp = timestamp++; |
38 | 33.0k | assert(!dfsNum.count(node) && "Revisit the same node again?"); |
39 | 33.0k | dfsNum[node] = myTimeStamp; |
40 | | |
41 | | // Traverse succecessor edges |
42 | 33.0k | for (auto childItr = GraphTraits::child_begin(node), |
43 | 33.0k | childIte = GraphTraits::child_end(node); |
44 | 56.3k | childItr != childIte; ++childItr) { |
45 | 23.3k | NodeType *succRep = getRep(*childItr); |
46 | 23.3k | if (!dfsNum.count(succRep)) |
47 | 19.9k | visit(succRep); |
48 | | |
49 | 23.3k | if (!inComponent.count(succRep) && dfsNum[node] > dfsNum[succRep]) |
50 | 0 | dfsNum[node] = dfsNum[succRep]; |
51 | 23.3k | } |
52 | | |
53 | | // See if we have any cycle detected |
54 | 33.0k | if (myTimeStamp != dfsNum[node]) { |
55 | | // If not, push the sccStack and go on |
56 | 0 | sccStack.push(node); |
57 | 0 | return; |
58 | 0 | } |
59 | | |
60 | | // Cycle detected |
61 | 33.0k | inComponent.insert(node); |
62 | 33.0k | while (!sccStack.empty()) { |
63 | 0 | NodeType const *cycleNode = sccStack.top(); |
64 | 0 | if (dfsNum[cycleNode] < myTimeStamp) |
65 | 0 | break; |
66 | | |
67 | 0 | processNodeOnCycle(cycleNode, node); |
68 | 0 | inComponent.insert(cycleNode); |
69 | 0 | sccStack.pop(); |
70 | 0 | } |
71 | | |
72 | 33.0k | processCycleRepNode(node); |
73 | 33.0k | } _ZN13CycleDetectorI20SparseBitVectorGraphE5visitEP24SparseBitVectorGraphNode Line | Count | Source | 36 | 25.8k | void visit(NodeType *node) { | 37 | 25.8k | unsigned myTimeStamp = timestamp++; | 38 | 25.8k | assert(!dfsNum.count(node) && "Revisit the same node again?"); | 39 | 25.8k | dfsNum[node] = myTimeStamp; | 40 | | | 41 | | // Traverse succecessor edges | 42 | 25.8k | for (auto childItr = GraphTraits::child_begin(node), | 43 | 25.8k | childIte = GraphTraits::child_end(node); | 44 | 49.1k | childItr != childIte; ++childItr) { | 45 | 23.2k | NodeType *succRep = getRep(*childItr); | 46 | 23.2k | if (!dfsNum.count(succRep)) | 47 | 19.8k | visit(succRep); | 48 | | | 49 | 23.2k | if (!inComponent.count(succRep) && dfsNum[node] > dfsNum[succRep]) | 50 | 0 | dfsNum[node] = dfsNum[succRep]; | 51 | 23.2k | } | 52 | | | 53 | | // See if we have any cycle detected | 54 | 25.8k | if (myTimeStamp != dfsNum[node]) { | 55 | | // If not, push the sccStack and go on | 56 | 0 | sccStack.push(node); | 57 | 0 | return; | 58 | 0 | } | 59 | | | 60 | | // Cycle detected | 61 | 25.8k | inComponent.insert(node); | 62 | 25.8k | while (!sccStack.empty()) { | 63 | 0 | NodeType const *cycleNode = sccStack.top(); | 64 | 0 | if (dfsNum[cycleNode] < myTimeStamp) | 65 | 0 | break; | 66 | | | 67 | 0 | processNodeOnCycle(cycleNode, node); | 68 | 0 | inComponent.insert(cycleNode); | 69 | 0 | sccStack.pop(); | 70 | 0 | } | 71 | | | 72 | 25.8k | processCycleRepNode(node); | 73 | 25.8k | } |
ConstraintSolving.cpp:_ZN13CycleDetectorIN12_GLOBAL__N_115ConstraintGraphEE5visitEPNS0_19ConstraintGraphNodeE Line | Count | Source | 36 | 7.14k | void visit(NodeType *node) { | 37 | 7.14k | unsigned myTimeStamp = timestamp++; | 38 | 7.14k | assert(!dfsNum.count(node) && "Revisit the same node again?"); | 39 | 7.14k | dfsNum[node] = myTimeStamp; | 40 | | | 41 | | // Traverse succecessor edges | 42 | 7.14k | for (auto childItr = GraphTraits::child_begin(node), | 43 | 7.14k | childIte = GraphTraits::child_end(node); | 44 | 7.25k | childItr != childIte; ++childItr) { | 45 | 108 | NodeType *succRep = getRep(*childItr); | 46 | 108 | if (!dfsNum.count(succRep)) | 47 | 108 | visit(succRep); | 48 | | | 49 | 108 | if (!inComponent.count(succRep) && dfsNum[node] > dfsNum[succRep]) | 50 | 0 | dfsNum[node] = dfsNum[succRep]; | 51 | 108 | } | 52 | | | 53 | | // See if we have any cycle detected | 54 | 7.14k | if (myTimeStamp != dfsNum[node]) { | 55 | | // If not, push the sccStack and go on | 56 | 0 | sccStack.push(node); | 57 | 0 | return; | 58 | 0 | } | 59 | | | 60 | | // Cycle detected | 61 | 7.14k | inComponent.insert(node); | 62 | 7.14k | while (!sccStack.empty()) { | 63 | 0 | NodeType const *cycleNode = sccStack.top(); | 64 | 0 | if (dfsNum[cycleNode] < myTimeStamp) | 65 | 0 | break; | 66 | | | 67 | 0 | processNodeOnCycle(cycleNode, node); | 68 | 0 | inComponent.insert(cycleNode); | 69 | 0 | sccStack.pop(); | 70 | 0 | } | 71 | | | 72 | 7.14k | processCycleRepNode(node); | 73 | 7.14k | } |
|
74 | | |
75 | | protected: |
76 | | // Nodes may get merged during the analysis. This function returns the merge |
77 | | // target (if the node is merged into another node) or the node itself (if the |
78 | | // nodes has not been merged into another node) |
79 | | virtual NodeType *getRep(NodeIndex node) = 0; |
80 | | // Specify how to process the non-rep nodes if a cycle is found |
81 | | virtual void processNodeOnCycle(NodeType const *node, |
82 | | NodeType const *repNode) = 0; |
83 | | // Specify how to process the rep nodes if a cycle is found |
84 | | virtual void processCycleRepNode(NodeType const *node) = 0; |
85 | | |
86 | | // Running the cycle detection algorithm on a given graph G |
87 | 1.76k | void runOnGraph(GraphType *graph) { |
88 | 1.76k | assert(sccStack.empty() && "sccStack is not empty before cycle detection!"); |
89 | 1.76k | assert(dfsNum.empty() && "dfsNum is not empty before cycle detection!"); |
90 | 1.76k | assert(inComponent.empty() && |
91 | 1.76k | "inComponent is not empty before cycle detection!"); |
92 | | |
93 | 1.76k | for (auto itr = GraphTraits::node_begin(graph), |
94 | 1.76k | ite = GraphTraits::node_end(graph); |
95 | 18.1k | itr != ite; ++itr) { |
96 | 16.4k | NodeType *repNode = getRep(itr->getNodeIndex()); |
97 | 16.4k | if (!dfsNum.count(repNode)) |
98 | 6.05k | visit(repNode); |
99 | 16.4k | } |
100 | | |
101 | 1.76k | assert(sccStack.empty() && "sccStack not empty after cycle detection!"); |
102 | 1.76k | } |
103 | | |
104 | | // Running the cycle detection algorithm on a given graph node. This function |
105 | | // is used when walking through the entire graph is not the desirable |
106 | | // behavior. |
107 | 7.03k | void runOnNode(NodeIndex node) { |
108 | 7.03k | assert(sccStack.empty() && "sccStack is not empty before cycle detection!"); |
109 | | |
110 | 7.03k | NodeType *repNode = getRep(node); |
111 | 7.03k | if (!dfsNum.count(repNode)) |
112 | 7.03k | visit(repNode); |
113 | | |
114 | 7.03k | assert(sccStack.empty() && "sccStack not empty after cycle detection!"); |
115 | 7.03k | } |
116 | | |
117 | 1.76k | void releaseSCCMemory() { |
118 | 1.76k | dfsNum.clear(); |
119 | 1.76k | inComponent.clear(); |
120 | 1.76k | } |
121 | | |
122 | | public: |
123 | 3.47k | CycleDetector() : timestamp(0) {} _ZN13CycleDetectorI20SparseBitVectorGraphEC2Ev Line | Count | Source | 123 | 1.76k | CycleDetector() : timestamp(0) {} |
ConstraintSolving.cpp:_ZN13CycleDetectorIN12_GLOBAL__N_115ConstraintGraphEEC2Ev Line | Count | Source | 123 | 1.71k | CycleDetector() : timestamp(0) {} |
|
124 | | |
125 | | // The public interface of running the detector |
126 | | virtual void run() = 0; |
127 | | }; |
128 | | |
129 | | #endif |