OpenADFortTk (including Open64 and OpenAnalysis references)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
SCC.cpp
Go to the documentation of this file.
1 
24 //************************** System Include Files ***************************
25 
26 #include <cassert>
27 
28 #include <map>
29 #include <set>
30 #include <stack>
31 
32 //*************************** User Include Files ****************************
33 
36 
37 //*************************** Forward Declarations **************************
38 
39 //------------------------------------------------------------------------
40 // LowLinkState is a private data structure used for finding SCC
41 // components.
42 //------------------------------------------------------------------------
43 
44 namespace OA {
45 
46 class LowLinkState {
47 public:
49  unsigned int sz = rifg->getHighWaterMarkNodeId() + 1;
50  mNodeStatus = new SCCNodeStatus[sz];
51  }
52 
54  delete[] mNodeStatus;
55  }
56 
57  // Mark methods
59  { mOld.insert(nid); }
60  unsigned int IsMarked(OA::RIFG::NodeId nid) {
61  MyNodeIdSet::const_iterator it = mOld.find(nid);
62  return (it != mOld.end());
63  }
64 
65  // Lowlink and depth-first methods
66  unsigned int& LOWLINK(OA::RIFG::NodeId nid)
67  { return mNodeStatus[nid].lowlink; }
68 
69  unsigned int& DFNUMBER(OA::RIFG::NodeId nid)
70  { return mNodeStatus[nid].dfnumber; }
71 
72  unsigned int& Count()
73  { return mCount; }
74 
75  // Stack methods
77  mNodeStatus[nid].inStack = true;
78  mNodeStack.push(node);
79  }
80 
82  { return mNodeStack.top(); }
83 
86  OA::RIFG::NodeId nid = rifg->getNodeId(node);
87  mNodeStack.pop();
88  mNodeStatus[nid].inStack = false;
89  return node;
90  }
91 
93  { return mNodeStatus[nid].inStack; }
94 
95 private:
96 
97  // SCCNodeStatus is a data structure to describe the current status
98  // of a SCC node.
99  class SCCNodeStatus {
100  public:
101  SCCNodeStatus(unsigned int l=0, unsigned int d=0, bool i=false)
102  : lowlink(l), dfnumber(d), inStack(i) { }
103 
104  unsigned int lowlink;
105  unsigned int dfnumber;
106  bool inStack;
107  };
108 
109  typedef std::set<OA::RIFG::NodeId> MyNodeIdSet;
110 
111  typedef std::stack<OA_ptr<DGraph::Interface::Node> > MyNodeStack;
112 
113 private:
115 
116  unsigned int mCount;
117  SCCNodeStatus* mNodeStatus; // indexed by OA::RIFG::NodeId
120 };
121 
122 } // end of namespace OA
123 
124 
125 //*************************** Forward Declarations **************************
126 
127 static void
128 CreateHelper(OA::SCCSet* sccSet,
131  OA::RIFG::NodeId vid,
132  OA::LowLinkState* state);
133 
134 
135 //***************************************************************************
136 
137 
138 //***************************************************************************
139 // SCCSet
140 //***************************************************************************
141 
142 namespace OA {
143 
145 {
146 }
147 
148 
150  OA_ptr<RIFG> rifg)
151 {
152  if (rifg.ptrEqual(0)) {
153  rifg = new OA::RIFG(graph, RIFG::getSourceNode(graph),
154  RIFG::getSinkNode(graph));
155  }
156  // assert(rifg->getGraph() == graph);
157  Create(graph, rifg);
158 }
159 
160 
161 void
163  OA_ptr<RIFG> rifg)
164 {
165  // Note: We use a RIFG in order to get dense node ids between 1 and n.
166  LowLinkState *state = new LowLinkState(rifg);
167  //LowLinkState *state = &ST;
168 
169  // if there exists a node not marked yet, visit it.
170  OA_ptr<DGraph::Interface::NodesIterator> it = graph->getNodesIterator();
171  for (; it->isValid(); ++(*it)) {
172  OA_ptr<DGraph::Interface::Node> node = it->current();
173  OA::RIFG::NodeId nid = rifg->getNodeId(node);
174  if ( !state->IsMarked(nid) ) {
175  CreateHelper(this, rifg, node, nid, state);
176  }
177  }
178 }
179 
180 
182 {
183  Destroy();
184 }
185 
186 
187 void
189 {
190  this->clear();
191 }
192 
193 
196 {
197  // N.B.: The implementation is a linear search and direct
198  // translation from the DSystem code. However, if this is going to
199  // be used a lot, we should probably create a map.
200  for (self_t::const_iterator it = this->begin(); it != this->end(); ++it) {
201  OA_ptr<SCCNodeSet> scc = *it;
202  if (scc->find(node) != scc->end()) {
203  return scc;
204  }
205  }
206  assert(false); // every node should be in a set
207  return OA_ptr<SCCNodeSet>(); // never reached!
208 }
209 
210 
211 void
212 SCCSet::dump(std::ostream& os)
213 {
214  using std::endl;
215 
216  os << "{ SCCSet: num SCC sets: " << this->size() << endl;
217  for (self_t::iterator it = this->begin(); it != this->end(); ++it) {
218  OA_ptr<SCCNodeSet> scc = *it;
219 
220  os << " { SCC: ";
221  SCCNodeSet::iterator sccIt = scc->begin();
222  for ( ; sccIt != scc->end(); ++sccIt) {
223  OA_ptr<DGraph::Interface::Node> node = *sccIt;
224  os << node->getId() << " ";
225  }
226  os << "}" << endl;
227  }
228 }
229 
230 
231 } // end of namespace OA
232 
233 
234 //***************************************************************************
235 // SCCSet helpers
236 //***************************************************************************
237 
238 static void
242  OA::RIFG::NodeId vid,
243  OA::LowLinkState* state)
244 {
245  using namespace OA;
246 
247  state->Mark(vid); // mark v
248  state->DFNUMBER(vid) = state->Count(); // set dfnumber
249  state->Count()++; // increment count by 1
250  state->LOWLINK(vid) = state->DFNUMBER(vid); // set lowlink number
251  state->Push(v, vid); // push v into stack
252 
253  // for each w which is on the adjacency list of v, there is an edge v->w
255  v->getSinkNodesIterator();
256  for (; it->isValid(); ++(*it)) {
257  OA_ptr<DGraph::Interface::Node> w = it->current();
258  OA::RIFG::NodeId wid = rifg->getNodeId(w);
259 
260  // if w is not marked yet
261  if (!state->IsMarked(wid)) {
262  CreateHelper(sccSet, rifg, w, wid, state);
263  state->LOWLINK(vid) = OA_MIN(state->LOWLINK(vid), state->LOWLINK(wid));
264  }
265  // w is already marked
266  else {
267  if ( state->DFNUMBER(wid) < state->DFNUMBER(vid) &&
268  state->IsOnStack(wid) ) {
269  state->LOWLINK(vid) = OA_MIN(state->DFNUMBER(wid),
270  state->LOWLINK(vid));
271  }
272  }
273  }
274 
275  // if lowlink[v] == DFNumber[v], the current Node in stack above
276  // v form a SCC.
277  if ( state->LOWLINK(vid) == state->DFNUMBER(vid) ) {
278  OA_ptr<SCCNodeSet> scc; scc = new SCCNodeSet;
279 
280  // pop x from top of stack, until x == v
282  do {
283  x = state->Pop();
284  scc->insert(x);
285  } while (x != v);
286 
287  // the SCC is complete now, add it to sccSet.
288  sccSet->insert(scc);
289  }
290 }
291