2 #include "nv50_ir_graph.h"
15 Iterator
*iter
= this->safeIteratorDFS();
17 for (; !iter
->end(); iter
->next())
18 reinterpret_cast<Node
*>(iter
->get())->cut();
23 void Graph::insert(Node
*node
)
30 root
->attach(node
, Edge::TREE
);
34 void Graph::Edge::unlink()
37 prev
[0]->next
[0] = next
[0];
38 next
[0]->prev
[0] = prev
[0];
39 if (origin
->out
== this)
40 origin
->out
= (next
[0] == this) ? NULL
: next
[0];
45 prev
[1]->next
[1] = next
[1];
46 next
[1]->prev
[1] = prev
[1];
47 if (target
->in
== this)
48 target
->in
= (next
[1] == this) ? NULL
: next
[1];
54 const char *Graph::Edge::typeStr() const
57 case TREE
: return "tree";
58 case FORWARD
: return "forward";
59 case BACK
: return "back";
60 case CROSS
: return "cross";
61 case DUMMY
: return "dummy";
68 Graph::Node::Node(void *priv
) : data(priv
),
69 in(0), out(0), graph(0),
71 inCount(0), outCount(0)
76 void Graph::Node::attach(Node
*node
, Edge::Type kind
)
78 Edge
*edge
= new Edge(this, node
, kind
);
82 edge
->next
[0] = this->out
;
83 edge
->prev
[0] = this->out
->prev
[0];
84 edge
->prev
[0]->next
[0] = edge
;
85 this->out
->prev
[0] = edge
;
90 edge
->next
[1] = node
->in
;
91 edge
->prev
[1] = node
->in
->prev
[1];
92 edge
->prev
[1]->next
[1] = edge
;
93 node
->in
->prev
[1] = edge
;
102 node
->graph
= this->graph
;
106 if (kind
== Edge::UNKNOWN
)
107 graph
->classifyEdges();
110 bool Graph::Node::detach(Graph::Node
*node
)
112 EdgeIterator ei
= this->outgoing();
113 for (; !ei
.end(); ei
.next())
114 if (ei
.getNode() == node
)
117 ERROR("no such node attached\n");
124 // Cut a node from the graph, deleting all attached edges.
125 void Graph::Node::cut()
127 if (!graph
|| (!in
&& !out
))
135 if (graph
->root
== this)
139 Graph::Edge::Edge(Node
*org
, Node
*tgt
, Type kind
)
145 next
[0] = next
[1] = this;
146 prev
[0] = prev
[1] = this;
150 Graph::Node::reachableBy(Node
*node
, Node
*term
)
154 const int seq
= graph
->nextSequence();
158 while (stack
.getSize()) {
159 pos
= reinterpret_cast<Node
*>(stack
.pop().u
.p
);
166 for (EdgeIterator ei
= pos
->outgoing(); !ei
.end(); ei
.next()) {
167 if (ei
.getType() == Edge::BACK
|| ei
.getType() == Edge::DUMMY
)
169 if (ei
.getNode()->visit(seq
))
170 stack
.push(ei
.getNode());
176 class DFSIterator
: public Graph::GraphIterator
179 DFSIterator(Graph
*graph
, const bool preorder
)
181 unsigned int seq
= graph
->nextSequence();
183 nodes
= new Graph::Node
* [graph
->getSize() + 1];
186 nodes
[graph
->getSize()] = 0;
188 if (graph
->getRoot()) {
189 graph
->getRoot()->visit(seq
);
190 search(graph
->getRoot(), preorder
, seq
);
200 void search(Graph::Node
*node
, const bool preorder
, const int sequence
)
203 nodes
[count
++] = node
;
205 for (Graph::EdgeIterator ei
= node
->outgoing(); !ei
.end(); ei
.next())
206 if (ei
.getNode()->visit(sequence
))
207 search(ei
.getNode(), preorder
, sequence
);
210 nodes
[count
++] = node
;
213 virtual bool end() const { return pos
>= count
; }
214 virtual void next() { if (pos
< count
) ++pos
; }
215 virtual void *get() const { return nodes
[pos
]; }
217 void reset() { pos
= 0; }
225 Graph::GraphIterator
*Graph::iteratorDFS(bool preorder
)
227 return new DFSIterator(this, preorder
);
230 Graph::GraphIterator
*Graph::safeIteratorDFS(bool preorder
)
232 return this->iteratorDFS(preorder
);
235 class CFGIterator
: public Graph::GraphIterator
238 CFGIterator(Graph
*graph
)
240 nodes
= new Graph::Node
* [graph
->getSize() + 1];
243 nodes
[graph
->getSize()] = 0;
245 // TODO: argh, use graph->sequence instead of tag and just raise it by > 1
247 for (iter
= graph
->iteratorDFS(); !iter
->end(); iter
->next())
248 reinterpret_cast<Graph::Node
*>(iter
->get())->tag
= 0;
249 graph
->putIterator(iter
);
251 if (graph
->getRoot())
252 search(graph
->getRoot(), graph
->nextSequence());
261 virtual void *get() const { return nodes
[pos
]; }
262 virtual bool end() const { return pos
>= count
; }
263 virtual void next() { if (pos
< count
) ++pos
; }
266 void search(Graph::Node
*node
, const int sequence
)
272 while (bb
.getSize()) {
273 node
= reinterpret_cast<Graph::Node
*>(bb
.pop().u
.p
);
275 if (!node
->visit(sequence
))
279 for (Graph::EdgeIterator ei
= node
->outgoing(); !ei
.end(); ei
.next()) {
280 switch (ei
.getType()) {
281 case Graph::Edge::TREE
:
282 case Graph::Edge::FORWARD
:
283 case Graph::Edge::DUMMY
:
284 if (++(ei
.getNode()->tag
) == ei
.getNode()->incidentCountFwd())
285 bb
.push(ei
.getNode());
287 case Graph::Edge::BACK
:
289 case Graph::Edge::CROSS
:
290 if (++(ei
.getNode()->tag
) == 1)
291 cross
.push(ei
.getNode());
294 assert(!"unknown edge kind in CFG");
298 nodes
[count
++] = node
;
300 if (bb
.getSize() == 0)
311 Graph::GraphIterator
*Graph::iteratorCFG()
313 return new CFGIterator(this);
316 Graph::GraphIterator
*Graph::safeIteratorCFG()
318 return this->iteratorCFG();
321 void Graph::classifyEdges()
326 for (iter
= new DFSIterator(this, true); !iter
->end(); iter
->next()) {
327 Node
*node
= reinterpret_cast<Node
*>(iter
->get());
333 classifyDFS(root
, (seq
= 0));
338 void Graph::classifyDFS(Node
*curr
, int& seq
)
346 for (edge
= curr
->out
; edge
; edge
= edge
->next
[0]) {
348 if (edge
->type
== Edge::DUMMY
)
351 if (node
->getSequence() == 0) {
352 edge
->type
= Edge::TREE
;
353 classifyDFS(node
, seq
);
355 if (node
->getSequence() > curr
->getSequence()) {
356 edge
->type
= Edge::FORWARD
;
358 edge
->type
= node
->tag
? Edge::BACK
: Edge::CROSS
;
362 for (edge
= curr
->in
; edge
; edge
= edge
->next
[1]) {
364 if (edge
->type
== Edge::DUMMY
)
367 if (node
->getSequence() == 0) {
368 edge
->type
= Edge::TREE
;
369 classifyDFS(node
, seq
);
371 if (node
->getSequence() > curr
->getSequence()) {
372 edge
->type
= Edge::FORWARD
;
374 edge
->type
= node
->tag
? Edge::BACK
: Edge::CROSS
;
381 } // namespace nv50_ir