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 Iterator
*iter
= this->safeIteratorDFS();
38 for (; !iter
->end(); iter
->next())
39 reinterpret_cast<Node
*>(iter
->get())->cut();
44 void Graph::insert(Node
*node
)
51 root
->attach(node
, Edge::TREE
);
55 void Graph::Edge::unlink()
58 prev
[0]->next
[0] = next
[0];
59 next
[0]->prev
[0] = prev
[0];
60 if (origin
->out
== this)
61 origin
->out
= (next
[0] == this) ? NULL
: next
[0];
66 prev
[1]->next
[1] = next
[1];
67 next
[1]->prev
[1] = prev
[1];
68 if (target
->in
== this)
69 target
->in
= (next
[1] == this) ? NULL
: next
[1];
75 const char *Graph::Edge::typeStr() const
78 case TREE
: return "tree";
79 case FORWARD
: return "forward";
80 case BACK
: return "back";
81 case CROSS
: return "cross";
82 case DUMMY
: return "dummy";
89 Graph::Node::Node(void *priv
) : data(priv
),
90 in(0), out(0), graph(0),
92 inCount(0), outCount(0)
97 void Graph::Node::attach(Node
*node
, Edge::Type kind
)
99 Edge
*edge
= new Edge(this, node
, kind
);
103 edge
->next
[0] = this->out
;
104 edge
->prev
[0] = this->out
->prev
[0];
105 edge
->prev
[0]->next
[0] = edge
;
106 this->out
->prev
[0] = edge
;
111 edge
->next
[1] = node
->in
;
112 edge
->prev
[1] = node
->in
->prev
[1];
113 edge
->prev
[1]->next
[1] = edge
;
114 node
->in
->prev
[1] = edge
;
123 node
->graph
= this->graph
;
127 if (kind
== Edge::UNKNOWN
)
128 graph
->classifyEdges();
131 bool Graph::Node::detach(Graph::Node
*node
)
133 EdgeIterator ei
= this->outgoing();
134 for (; !ei
.end(); ei
.next())
135 if (ei
.getNode() == node
)
138 ERROR("no such node attached\n");
145 // Cut a node from the graph, deleting all attached edges.
146 void Graph::Node::cut()
154 if (graph
->root
== this)
160 Graph::Edge::Edge(Node
*org
, Node
*tgt
, Type kind
)
166 next
[0] = next
[1] = this;
167 prev
[0] = prev
[1] = this;
171 Graph::Node::reachableBy(Node
*node
, Node
*term
)
175 const int seq
= graph
->nextSequence();
179 while (stack
.getSize()) {
180 pos
= reinterpret_cast<Node
*>(stack
.pop().u
.p
);
187 for (EdgeIterator ei
= pos
->outgoing(); !ei
.end(); ei
.next()) {
188 if (ei
.getType() == Edge::BACK
|| ei
.getType() == Edge::DUMMY
)
190 if (ei
.getNode()->visit(seq
))
191 stack
.push(ei
.getNode());
197 class DFSIterator
: public Graph::GraphIterator
200 DFSIterator(Graph
*graph
, const bool preorder
)
202 unsigned int seq
= graph
->nextSequence();
204 nodes
= new Graph::Node
* [graph
->getSize() + 1];
207 nodes
[graph
->getSize()] = 0;
209 if (graph
->getRoot()) {
210 graph
->getRoot()->visit(seq
);
211 search(graph
->getRoot(), preorder
, seq
);
221 void search(Graph::Node
*node
, const bool preorder
, const int sequence
)
224 nodes
[count
++] = node
;
226 for (Graph::EdgeIterator ei
= node
->outgoing(); !ei
.end(); ei
.next())
227 if (ei
.getNode()->visit(sequence
))
228 search(ei
.getNode(), preorder
, sequence
);
231 nodes
[count
++] = node
;
234 virtual bool end() const { return pos
>= count
; }
235 virtual void next() { if (pos
< count
) ++pos
; }
236 virtual void *get() const { return nodes
[pos
]; }
238 void reset() { pos
= 0; }
246 Graph::GraphIterator
*Graph::iteratorDFS(bool preorder
)
248 return new DFSIterator(this, preorder
);
251 Graph::GraphIterator
*Graph::safeIteratorDFS(bool preorder
)
253 return this->iteratorDFS(preorder
);
256 class CFGIterator
: public Graph::GraphIterator
259 CFGIterator(Graph
*graph
)
261 nodes
= new Graph::Node
* [graph
->getSize() + 1];
264 nodes
[graph
->getSize()] = 0;
266 // TODO: argh, use graph->sequence instead of tag and just raise it by > 1
268 for (iter
= graph
->iteratorDFS(); !iter
->end(); iter
->next())
269 reinterpret_cast<Graph::Node
*>(iter
->get())->tag
= 0;
270 graph
->putIterator(iter
);
272 if (graph
->getRoot())
273 search(graph
->getRoot(), graph
->nextSequence());
282 virtual void *get() const { return nodes
[pos
]; }
283 virtual bool end() const { return pos
>= count
; }
284 virtual void next() { if (pos
< count
) ++pos
; }
287 void search(Graph::Node
*node
, const int sequence
)
293 while (bb
.getSize()) {
294 node
= reinterpret_cast<Graph::Node
*>(bb
.pop().u
.p
);
296 if (!node
->visit(sequence
))
300 for (Graph::EdgeIterator ei
= node
->outgoing(); !ei
.end(); ei
.next()) {
301 switch (ei
.getType()) {
302 case Graph::Edge::TREE
:
303 case Graph::Edge::FORWARD
:
304 case Graph::Edge::DUMMY
:
305 if (++(ei
.getNode()->tag
) == ei
.getNode()->incidentCountFwd())
306 bb
.push(ei
.getNode());
308 case Graph::Edge::BACK
:
310 case Graph::Edge::CROSS
:
311 if (++(ei
.getNode()->tag
) == 1)
312 cross
.push(ei
.getNode());
315 assert(!"unknown edge kind in CFG");
319 nodes
[count
++] = node
;
321 if (bb
.getSize() == 0)
332 Graph::GraphIterator
*Graph::iteratorCFG()
334 return new CFGIterator(this);
337 Graph::GraphIterator
*Graph::safeIteratorCFG()
339 return this->iteratorCFG();
342 void Graph::classifyEdges()
347 for (iter
= new DFSIterator(this, true); !iter
->end(); iter
->next()) {
348 Node
*node
= reinterpret_cast<Node
*>(iter
->get());
354 classifyDFS(root
, (seq
= 0));
359 void Graph::classifyDFS(Node
*curr
, int& seq
)
367 for (edge
= curr
->out
; edge
; edge
= edge
->next
[0]) {
369 if (edge
->type
== Edge::DUMMY
)
372 if (node
->getSequence() == 0) {
373 edge
->type
= Edge::TREE
;
374 classifyDFS(node
, seq
);
376 if (node
->getSequence() > curr
->getSequence()) {
377 edge
->type
= Edge::FORWARD
;
379 edge
->type
= node
->tag
? Edge::BACK
: Edge::CROSS
;
383 for (edge
= curr
->in
; edge
; edge
= edge
->next
[1]) {
385 if (edge
->type
== Edge::DUMMY
)
388 if (node
->getSequence() == 0) {
389 edge
->type
= Edge::TREE
;
390 classifyDFS(node
, seq
);
392 if (node
->getSequence() > curr
->getSequence()) {
393 edge
->type
= Edge::FORWARD
;
395 edge
->type
= node
->tag
? Edge::BACK
: Edge::CROSS
;
402 } // namespace nv50_ir