2 * Copyright 2011 Christoph Bumiller
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include "nv50_ir_graph.h"
36 for (IteratorRef it
= safeIteratorDFS(); !it
->end(); it
->next())
37 reinterpret_cast<Node
*>(it
->get())->cut();
40 void Graph::insert(Node
*node
)
49 void Graph::Edge::unlink()
52 prev
[0]->next
[0] = next
[0];
53 next
[0]->prev
[0] = prev
[0];
54 if (origin
->out
== this)
55 origin
->out
= (next
[0] == this) ? NULL
: next
[0];
60 prev
[1]->next
[1] = next
[1];
61 next
[1]->prev
[1] = prev
[1];
62 if (target
->in
== this)
63 target
->in
= (next
[1] == this) ? NULL
: next
[1];
69 const char *Graph::Edge::typeStr() const
72 case TREE
: return "tree";
73 case FORWARD
: return "forward";
74 case BACK
: return "back";
75 case CROSS
: return "cross";
76 case DUMMY
: return "dummy";
83 Graph::Node::Node(void *priv
) : data(priv
),
84 in(0), out(0), graph(0),
86 inCount(0), outCount(0)
91 void Graph::Node::attach(Node
*node
, Edge::Type kind
)
93 Edge
*edge
= new Edge(this, node
, kind
);
97 edge
->next
[0] = this->out
;
98 edge
->prev
[0] = this->out
->prev
[0];
99 edge
->prev
[0]->next
[0] = edge
;
100 this->out
->prev
[0] = edge
;
105 edge
->next
[1] = node
->in
;
106 edge
->prev
[1] = node
->in
->prev
[1];
107 edge
->prev
[1]->next
[1] = edge
;
108 node
->in
->prev
[1] = edge
;
115 assert(graph
|| node
->graph
);
119 node
->graph
->insert(this);
121 if (kind
== Edge::UNKNOWN
)
122 graph
->classifyEdges();
125 bool Graph::Node::detach(Graph::Node
*node
)
127 EdgeIterator ei
= this->outgoing();
128 for (; !ei
.end(); ei
.next())
129 if (ei
.getNode() == node
)
132 ERROR("no such node attached\n");
139 // Cut a node from the graph, deleting all attached edges.
140 void Graph::Node::cut()
148 if (graph
->root
== this)
154 Graph::Edge::Edge(Node
*org
, Node
*tgt
, Type kind
)
160 next
[0] = next
[1] = this;
161 prev
[0] = prev
[1] = this;
165 Graph::Node::reachableBy(Node
*node
, Node
*term
)
169 const int seq
= graph
->nextSequence();
173 while (stack
.getSize()) {
174 pos
= reinterpret_cast<Node
*>(stack
.pop().u
.p
);
181 for (EdgeIterator ei
= pos
->outgoing(); !ei
.end(); ei
.next()) {
182 if (ei
.getType() == Edge::BACK
|| ei
.getType() == Edge::DUMMY
)
184 if (ei
.getNode()->visit(seq
))
185 stack
.push(ei
.getNode());
191 class DFSIterator
: public Iterator
194 DFSIterator(Graph
*graph
, const bool preorder
)
196 unsigned int seq
= graph
->nextSequence();
198 nodes
= new Graph::Node
* [graph
->getSize() + 1];
201 nodes
[graph
->getSize()] = 0;
203 if (graph
->getRoot()) {
204 graph
->getRoot()->visit(seq
);
205 search(graph
->getRoot(), preorder
, seq
);
215 void search(Graph::Node
*node
, const bool preorder
, const int sequence
)
218 nodes
[count
++] = node
;
220 for (Graph::EdgeIterator ei
= node
->outgoing(); !ei
.end(); ei
.next())
221 if (ei
.getNode()->visit(sequence
))
222 search(ei
.getNode(), preorder
, sequence
);
225 nodes
[count
++] = node
;
228 virtual bool end() const { return pos
>= count
; }
229 virtual void next() { if (pos
< count
) ++pos
; }
230 virtual void *get() const { return nodes
[pos
]; }
232 void reset() { pos
= 0; }
240 IteratorRef
Graph::iteratorDFS(bool preorder
)
242 return IteratorRef(new DFSIterator(this, preorder
));
245 IteratorRef
Graph::safeIteratorDFS(bool preorder
)
247 return this->iteratorDFS(preorder
);
250 class CFGIterator
: public Iterator
253 CFGIterator(Graph
*graph
)
255 nodes
= new Graph::Node
* [graph
->getSize() + 1];
258 nodes
[graph
->getSize()] = 0;
260 // TODO: argh, use graph->sequence instead of tag and just raise it by > 1
261 for (IteratorRef it
= graph
->iteratorDFS(); !it
->end(); it
->next())
262 reinterpret_cast<Graph::Node
*>(it
->get())->tag
= 0;
264 if (graph
->getRoot())
265 search(graph
->getRoot(), graph
->nextSequence());
274 virtual void *get() const { return nodes
[pos
]; }
275 virtual bool end() const { return pos
>= count
; }
276 virtual void next() { if (pos
< count
) ++pos
; }
279 void search(Graph::Node
*node
, const int sequence
)
285 while (bb
.getSize()) {
286 node
= reinterpret_cast<Graph::Node
*>(bb
.pop().u
.p
);
288 if (!node
->visit(sequence
))
292 for (Graph::EdgeIterator ei
= node
->outgoing(); !ei
.end(); ei
.next()) {
293 switch (ei
.getType()) {
294 case Graph::Edge::TREE
:
295 case Graph::Edge::FORWARD
:
296 case Graph::Edge::DUMMY
:
297 if (++(ei
.getNode()->tag
) == ei
.getNode()->incidentCountFwd())
298 bb
.push(ei
.getNode());
300 case Graph::Edge::BACK
:
302 case Graph::Edge::CROSS
:
303 if (++(ei
.getNode()->tag
) == 1)
304 cross
.push(ei
.getNode());
307 assert(!"unknown edge kind in CFG");
311 nodes
[count
++] = node
;
313 if (bb
.getSize() == 0)
324 IteratorRef
Graph::iteratorCFG()
326 return IteratorRef(new CFGIterator(this));
329 IteratorRef
Graph::safeIteratorCFG()
331 return this->iteratorCFG();
334 void Graph::classifyEdges()
338 for (IteratorRef it
= iteratorDFS(true); !it
->end(); it
->next()) {
339 Node
*node
= reinterpret_cast<Node
*>(it
->get());
344 classifyDFS(root
, (seq
= 0));
349 void Graph::classifyDFS(Node
*curr
, int& seq
)
357 for (edge
= curr
->out
; edge
; edge
= edge
->next
[0]) {
359 if (edge
->type
== Edge::DUMMY
)
362 if (node
->getSequence() == 0) {
363 edge
->type
= Edge::TREE
;
364 classifyDFS(node
, seq
);
366 if (node
->getSequence() > curr
->getSequence()) {
367 edge
->type
= Edge::FORWARD
;
369 edge
->type
= node
->tag
? Edge::BACK
: Edge::CROSS
;
373 for (edge
= curr
->in
; edge
; edge
= edge
->next
[1]) {
375 if (edge
->type
== Edge::DUMMY
)
378 if (node
->getSequence() == 0) {
379 edge
->type
= Edge::TREE
;
380 classifyDFS(node
, seq
);
382 if (node
->getSequence() > curr
->getSequence()) {
383 edge
->type
= Edge::FORWARD
;
385 edge
->type
= node
->tag
? Edge::BACK
: Edge::CROSS
;
392 } // namespace nv50_ir