Path: blob/21.2-virgl/src/gallium/drivers/nouveau/codegen/nv50_ir_graph.h
4574 views
/*1* Copyright 2011 Christoph Bumiller2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*/2122#ifndef __NV50_IR_GRAPH_H__23#define __NV50_IR_GRAPH_H__2425#include "codegen/nv50_ir_util.h"26#include <vector>2728namespace nv50_ir {2930#define ITER_NODE(x) reinterpret_cast<Graph::Node *>((x).get())31#define ITER_EDGE(x) reinterpret_cast<Graph::Edge *>((x).get())3233// A connected graph.34class Graph35{36public:37class Node;3839class Edge40{41public:42enum Type43{44UNKNOWN,45TREE,46FORWARD,47BACK,48CROSS, // e.g. loop break49};5051Edge(Node *dst, Node *src, Type kind);52~Edge() { unlink(); }5354inline Node *getOrigin() const { return origin; }55inline Node *getTarget() const { return target; }5657inline Type getType() const { return type; }58const char *typeStr() const;5960private:61Node *origin;62Node *target;6364Type type;65Edge *next[2]; // next edge outgoing/incident from/to origin/target66Edge *prev[2];6768void unlink();6970friend class Graph;71};7273class EdgeIterator : public Iterator74{75public:76EdgeIterator() : e(0), t(0), d(0), rev(false) { }77EdgeIterator(Graph::Edge *first, int dir, bool reverse)78: d(dir), rev(reverse)79{80t = e = ((rev && first) ? first->prev[d] : first);81}8283virtual void next()84{85Graph::Edge *n = (rev ? e->prev[d] : e->next[d]);86e = (n == t ? NULL : n);87}88virtual bool end() const { return !e; }89virtual void *get() const { return e; }9091inline Node *getNode() const { assert(e); return d ?92e->origin : e->target; }93inline Edge *getEdge() const { return e; }94inline Edge::Type getType() { return e ? e->getType() : Edge::UNKNOWN; }9596private:97Graph::Edge *e;98Graph::Edge *t;99int d;100bool rev;101};102103class Node104{105public:106Node(void *);107~Node() { cut(); }108109void attach(Node *, Edge::Type);110bool detach(Node *);111void cut();112113inline EdgeIterator outgoing(bool reverse = false) const;114inline EdgeIterator incident(bool reverse = false) const;115116inline Node *parent() const; // returns NULL if count(incident edges) != 1117118bool reachableBy(const Node *node, const Node *term) const;119120inline bool visit(int);121inline int getSequence() const;122123inline int incidentCountFwd() const; // count of incident non-back edges124inline int incidentCount() const { return inCount; }125inline int outgoingCount() const { return outCount; }126127Graph *getGraph() const { return graph; }128129void *data;130131private:132Edge *in;133Edge *out;134Graph *graph;135136int visited;137138int16_t inCount;139int16_t outCount;140public:141int tag; // for temporary use142143friend class Graph;144};145146public:147Graph();148virtual ~Graph(); // does *not* free the nodes (make it an option ?)149150inline Node *getRoot() const { return root; }151152inline unsigned int getSize() const { return size; }153154inline int nextSequence();155156void insert(Node *node); // attach to or set as root157158IteratorRef iteratorDFS(bool preorder = true);159IteratorRef iteratorCFG();160161// safe iterators are unaffected by changes to the *edges* of the graph162IteratorRef safeIteratorDFS(bool preorder = true);163IteratorRef safeIteratorCFG();164165void classifyEdges();166167// @weights: indexed by Node::tag168int findLightestPathWeight(Node *, Node *, const std::vector<int>& weights);169170private:171void classifyDFS(Node *, int&);172173private:174Node *root;175unsigned int size;176int sequence;177};178179int Graph::nextSequence()180{181return ++sequence;182}183184Graph::Node *Graph::Node::parent() const185{186if (inCount != 1)187return NULL;188assert(in);189return in->origin;190}191192bool Graph::Node::visit(int v)193{194if (visited == v)195return false;196visited = v;197return true;198}199200int Graph::Node::getSequence() const201{202return visited;203}204205Graph::EdgeIterator Graph::Node::outgoing(bool reverse) const206{207return EdgeIterator(out, 0, reverse);208}209210Graph::EdgeIterator Graph::Node::incident(bool reverse) const211{212return EdgeIterator(in, 1, reverse);213}214215int Graph::Node::incidentCountFwd() const216{217int n = 0;218for (EdgeIterator ei = incident(); !ei.end(); ei.next())219if (ei.getType() != Edge::BACK)220++n;221return n;222}223224} // namespace nv50_ir225226#endif // __NV50_IR_GRAPH_H__227228229