Static Value-Flow Analysis
SCC.h
Go to the documentation of this file.
1 //===- SCC.h -- SCC detection algorithm---------------------------------------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-2017> <Yulei Sui>
6 //
7 
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
17 
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 /*
24  * SCC.h
25  *
26  * Esko Nuutila and Eljas Soisalon-Soininen, "On finding the
27  * strongly connected components in a directed graph".
28  * Inf. Process. Letters, 49(1):9-14, 1994.
29  *
30  * The implementation is derived from the pseudo code in the following paper:
31  * Pereira and Berlin, "Wave Propagation and Deep Propagation for Pointer Analysis",
32  * CGO 2009, 126-135, 2009.
33  *
34  * And influenced by implementation from Open64 compiler
35  *
36  * Created on: Jul 12, 2013
37  * Author: yusui
38  */
39 
40 #ifndef SCC_H_
41 #define SCC_H_
42 
43 #include "SVFIR/SVFValue.h" // for NodeBS
44 #include <limits.h>
45 #include <stack>
46 #include <map>
47 
48 namespace SVF
49 {
50 
51 class GNodeSCCInfo;
52 
53 template<class GraphType>
55 {
56 
57 private:
60  typedef typename GTraits::NodeRef GNODE;
61  typedef typename GTraits::nodes_iterator node_iterator;
62  typedef typename GTraits::ChildIteratorType child_iterator;
63  typedef unsigned NodeID ;
64 
65 public:
66  typedef std::stack<NodeID> GNodeStack;
67 
69  {
70  public:
71  GNodeSCCInfo() : _visited(false), _inSCC(false), _rep(UINT_MAX) {}
72 
73  inline bool visited(void) const
74  {
75  return _visited;
76  }
77  inline void visited(bool v)
78  {
79  _visited = v;
80  }
81  inline bool inSCC(void) const
82  {
83  return _inSCC;
84  }
85  inline void inSCC(bool v)
86  {
87  _inSCC = v;
88  }
89  inline NodeID rep(void)const
90  {
91  return _rep;
92  }
93  inline void rep(NodeID n)
94  {
95  _rep = n;
96  }
97  inline void addSubNodes(NodeID n)
98  {
99  _subNodes.set(n);
100  }
101  inline NodeBS& subNodes()
102  {
103  return _subNodes;
104  }
105  inline const NodeBS& subNodes() const
106  {
107  return _subNodes;
108  }
109  private:
110  bool _visited;
111  bool _inSCC;
114  };
115 
118 
119  SCCDetection(const GraphType &GT)
120  : _graph(GT),
121  _I(0)
122  {}
123 
124 
125  // Return a handle to the stack of nodes in topological
126  // order. This will be used to seed the initial solution
127  // and improve efficiency.
129  {
130  return _T;
131  }
132 
133  const inline GNODESCCInfoMap &GNodeSCCInfo() const
134  {
135  return _NodeSCCAuxInfo;
136  }
137 
139  inline NodeID repNode(NodeID n) const
140  {
141  typename GNODESCCInfoMap::const_iterator it = _NodeSCCAuxInfo.find(n);
142  assert(it!=_NodeSCCAuxInfo.end() && "scc rep not found");
143  NodeID rep = it->second.rep();
144  return rep!= UINT_MAX ? rep : n ;
145  }
146 
147 
149  inline bool isInCycle(NodeID n) const
150  {
151  NodeID rep = repNode(n);
152  // multi-node cycle
153  if (subNodes(rep).count() > 1)
154  {
155  return true;
156  }
157  // self-cycle
158  else
159  {
160  child_iterator EI = GTraits::direct_child_begin(Node(rep));
161  child_iterator EE = GTraits::direct_child_end(Node(rep));
162  for (; EI != EE; ++EI)
163  {
164  NodeID w = Node_Index(*EI);
165  if(w==rep)
166  return true;
167  }
168  return false;
169  }
170  }
171 
173  inline const NodeBS& subNodes(NodeID n) const
174  {
175  typename GNODESCCInfoMap::const_iterator it = _NodeSCCAuxInfo.find(n);
176  assert(it!=_NodeSCCAuxInfo.end() && "scc rep not found");
177  return it->second.subNodes();
178  }
179 
181  inline const NodeBS &getRepNodes() const
182  {
183  return repNodes;
184  }
185 
186  const inline GraphType & graph()
187  {
188  return _graph;
189  }
190 private:
191 
193 
194  const GraphType & _graph;
200 
201  inline bool visited(NodeID n)
202  {
203  return _NodeSCCAuxInfo[n].visited();
204  }
205  inline bool inSCC(NodeID n)
206  {
207  return _NodeSCCAuxInfo[n].inSCC();
208  }
209 
210  inline void setVisited(NodeID n,bool v)
211  {
212  _NodeSCCAuxInfo[n].visited(v);
213  }
214  inline void setInSCC(NodeID n,bool v)
215  {
216  _NodeSCCAuxInfo[n].inSCC(v);
217  }
218  inline void rep(NodeID n, NodeID r)
219  {
220  _NodeSCCAuxInfo[n].rep(r);
221  _NodeSCCAuxInfo[r].addSubNodes(n);
222  if (n != r)
223  {
224  _NodeSCCAuxInfo[n].subNodes().clear();
225  repNodes.reset(n);
226  repNodes.set(r);
227  }
228  }
229 
230  inline NodeID rep(NodeID n)
231  {
232  return _NodeSCCAuxInfo[n].rep();
233  }
234  inline bool isInSCC(NodeID n)
235  {
236  return _NodeSCCAuxInfo[n].inSCC();
237  }
238 
239  inline GNODE Node(NodeID id) const
240  {
241  return GTraits::getNode(_graph, id);
242  }
243 
244  inline NodeID Node_Index(GNODE node) const
245  {
246  return GTraits::getNodeID(node);
247  }
248 
249  void visit(NodeID v)
250  {
251  // SVFUtil::outs() << "visit GNODE: " << Node_Index(v)<< "\n";
252  _I += 1;
253  _D[v] = _I;
254  this->rep(v,v);
255  this->setVisited(v,true);
256 
257  child_iterator EI = GTraits::direct_child_begin(Node(v));
258  child_iterator EE = GTraits::direct_child_end(Node(v));
259 
260  for (; EI != EE; ++EI)
261  {
262  NodeID w = Node_Index(*EI);
263 
264  if (!this->visited(w))
265  visit(w);
266  if (!this->inSCC(w))
267  {
268  NodeID rep;
269  rep = _D[this->rep(v)] < _D[this->rep(w)] ?
270  this->rep(v) : this->rep(w);
271  this->rep(v,rep);
272  }
273  }
274  if (this->rep(v) == v)
275  {
276  this->setInSCC(v,true);
277  while (!_SS.empty())
278  {
279  NodeID w = _SS.top();
280  if (_D[w] <= _D[v])
281  break;
282  else
283  {
284  _SS.pop();
285  this->setInSCC(w,true);
286  this->rep(w,v);
287  }
288  }
289  _T.push(v);
290  }
291  else
292  _SS.push(v);
293  }
294 
295  void clear()
296  {
297  _NodeSCCAuxInfo.clear();
298  _I = 0;
299  _D.clear();
300  repNodes.clear();
301  while(!_SS.empty())
302  _SS.pop();
303  while(!_T.empty())
304  _T.pop();
305  }
306 public:
307 
308  void find(void)
309  {
310  // Visit each unvisited root node. A root node is defined
311  // to be a node that has no incoming copy/skew edges
312  clear();
313  node_iterator I = GTraits::nodes_begin(_graph);
314  node_iterator E = GTraits::nodes_end(_graph);
315  for (; I != E; ++I)
316  {
317  NodeID node = Node_Index(*I);
318  if (!this->visited(node))
319  {
320  // We skip any nodes that have a representative other than
321  // themselves. Such nodes occur as a result of merging
322  // nodes either through unifying an ACC or other node
323  // merging optimizations. Any such node should have no
324  // outgoing edges and therefore should no longer be a member
325  // of an SCC.
326  if (this->rep(node) == UINT_MAX || this->rep(node) == node)
327  visit(node);
328  else
329  this->visited(node);
330  }
331  }
332  }
333 
334  void find(NodeSet &candidates)
335  {
336  // This function is reloaded to only visit candidate NODES
337  clear();
338  for (NodeID node : candidates)
339  {
340  if (!this->visited(node))
341  {
342  if (this->rep(node) == UINT_MAX || this->rep(node) == node)
343  visit(node);
344  else
345  this->visited(node);
346  }
347  }
348  }
349 
350 };
351 
352 } // End namespace SVF
353 
354 #endif /* SCC_H_ */
#define false
Definition: cJSON.cpp:70
cJSON * n
Definition: cJSON.cpp:2558
int count
Definition: cJSON.h:216
void rep(NodeID n)
Definition: SCC.h:93
void addSubNodes(NodeID n)
Definition: SCC.h:97
void visited(bool v)
Definition: SCC.h:77
bool visited(void) const
Definition: SCC.h:73
const NodeBS & subNodes() const
Definition: SCC.h:105
NodeID rep(void) const
Definition: SCC.h:89
bool inSCC(void) const
Definition: SCC.h:81
GNodeStack _T
Definition: SCC.h:198
void rep(NodeID n, NodeID r)
Definition: SCC.h:218
GNodeStack _SS
Definition: SCC.h:197
void find(void)
Definition: SCC.h:308
const GraphType & graph()
Definition: SCC.h:186
SCCDetection(const GraphType &GT)
Definition: SCC.h:119
void find(NodeSet &candidates)
Definition: SCC.h:334
const GraphType & _graph
Definition: SCC.h:194
NodeBS repNodes
Definition: SCC.h:199
void clear()
Definition: SCC.h:295
NodeID repNode(NodeID n) const
get the rep node if not found return itself
Definition: SCC.h:139
const NodeBS & getRepNodes() const
get all repNodeID
Definition: SCC.h:181
unsigned NodeID
Definition: SCC.h:63
GNODESCCInfoMap _NodeSCCAuxInfo
Definition: SCC.h:192
Map< NodeID, GNodeSCCInfo > GNODESCCInfoMap
Definition: SCC.h:116
NodeToNodeMap _D
Definition: SCC.h:196
bool isInCycle(NodeID n) const
whether the node is in a cycle
Definition: SCC.h:149
NodeID Node_Index(GNODE node) const
Definition: SCC.h:244
bool inSCC(NodeID n)
Definition: SCC.h:205
GNODE Node(NodeID id) const
Definition: SCC.h:239
GNodeStack & topoNodeStack()
Definition: SCC.h:128
const NodeBS & subNodes(NodeID n) const
get all subnodes in one scc, if size is empty insert itself into the set
Definition: SCC.h:173
GTraits::NodeRef GNODE
Definition: SCC.h:60
Map< NodeID, NodeID > NodeToNodeMap
Definition: SCC.h:117
std::stack< NodeID > GNodeStack
Definition: SCC.h:66
SVF::GenericGraphTraits< GraphType > GTraits
Define the GTraits and node iterator for printing.
Definition: SCC.h:59
NodeID _I
Definition: SCC.h:195
bool visited(NodeID n)
Definition: SCC.h:201
void setInSCC(NodeID n, bool v)
Definition: SCC.h:214
const GNODESCCInfoMap & GNodeSCCInfo() const
Definition: SCC.h:133
GTraits::nodes_iterator node_iterator
Definition: SCC.h:61
GTraits::ChildIteratorType child_iterator
Definition: SCC.h:62
NodeID rep(NodeID n)
Definition: SCC.h:230
void setVisited(NodeID n, bool v)
Definition: SCC.h:210
void visit(NodeID v)
Definition: SCC.h:249
bool isInSCC(NodeID n)
Definition: SCC.h:234
void set(unsigned Idx)
void reset(unsigned Idx)
for isBitcode
Definition: BasicTypes.h:68
Set< NodeID > NodeSet
Definition: GeneralType.h:113
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
typename GraphType::UnknownGraphTypeError NodeRef
Definition: GraphTraits.h:80