Clone of mesa.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

nv50_ir_graph.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /*
  2. * Copyright 2011 Christoph Bumiller
  3. *
  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:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. */
  22. #include "nv50_ir_graph.h"
  23. #include <limits>
  24. #include <list>
  25. #include <stack>
  26. #include "nv50_ir.h"
  27. namespace nv50_ir {
  28. Graph::Graph()
  29. {
  30. root = NULL;
  31. size = 0;
  32. sequence = 0;
  33. }
  34. Graph::~Graph()
  35. {
  36. for (IteratorRef it = safeIteratorDFS(); !it->end(); it->next())
  37. reinterpret_cast<Node *>(it->get())->cut();
  38. }
  39. void Graph::insert(Node *node)
  40. {
  41. if (!root)
  42. root = node;
  43. node->graph = this;
  44. size++;
  45. }
  46. void Graph::Edge::unlink()
  47. {
  48. if (origin) {
  49. prev[0]->next[0] = next[0];
  50. next[0]->prev[0] = prev[0];
  51. if (origin->out == this)
  52. origin->out = (next[0] == this) ? NULL : next[0];
  53. --origin->outCount;
  54. }
  55. if (target) {
  56. prev[1]->next[1] = next[1];
  57. next[1]->prev[1] = prev[1];
  58. if (target->in == this)
  59. target->in = (next[1] == this) ? NULL : next[1];
  60. --target->inCount;
  61. }
  62. }
  63. const char *Graph::Edge::typeStr() const
  64. {
  65. switch (type) {
  66. case TREE: return "tree";
  67. case FORWARD: return "forward";
  68. case BACK: return "back";
  69. case CROSS: return "cross";
  70. case DUMMY: return "dummy";
  71. case UNKNOWN:
  72. default:
  73. return "unk";
  74. }
  75. }
  76. Graph::Node::Node(void *priv) : data(priv),
  77. in(0), out(0), graph(0),
  78. visited(0),
  79. inCount(0), outCount(0)
  80. {
  81. // nothing to do
  82. }
  83. void Graph::Node::attach(Node *node, Edge::Type kind)
  84. {
  85. Edge *edge = new Edge(this, node, kind);
  86. // insert head
  87. if (this->out) {
  88. edge->next[0] = this->out;
  89. edge->prev[0] = this->out->prev[0];
  90. edge->prev[0]->next[0] = edge;
  91. this->out->prev[0] = edge;
  92. }
  93. this->out = edge;
  94. if (node->in) {
  95. edge->next[1] = node->in;
  96. edge->prev[1] = node->in->prev[1];
  97. edge->prev[1]->next[1] = edge;
  98. node->in->prev[1] = edge;
  99. }
  100. node->in = edge;
  101. ++this->outCount;
  102. ++node->inCount;
  103. assert(graph || node->graph);
  104. if (!node->graph)
  105. graph->insert(node);
  106. if (!graph)
  107. node->graph->insert(this);
  108. if (kind == Edge::UNKNOWN)
  109. graph->classifyEdges();
  110. }
  111. bool Graph::Node::detach(Graph::Node *node)
  112. {
  113. EdgeIterator ei = this->outgoing();
  114. for (; !ei.end(); ei.next())
  115. if (ei.getNode() == node)
  116. break;
  117. if (ei.end()) {
  118. ERROR("no such node attached\n");
  119. return false;
  120. }
  121. delete ei.getEdge();
  122. return true;
  123. }
  124. // Cut a node from the graph, deleting all attached edges.
  125. void Graph::Node::cut()
  126. {
  127. while (out)
  128. delete out;
  129. while (in)
  130. delete in;
  131. if (graph) {
  132. if (graph->root == this)
  133. graph->root = NULL;
  134. graph = NULL;
  135. }
  136. }
  137. Graph::Edge::Edge(Node *org, Node *tgt, Type kind)
  138. {
  139. target = tgt;
  140. origin = org;
  141. type = kind;
  142. next[0] = next[1] = this;
  143. prev[0] = prev[1] = this;
  144. }
  145. bool
  146. Graph::Node::reachableBy(const Node *node, const Node *term) const
  147. {
  148. std::stack<const Node *> stack;
  149. const Node *pos = NULL;
  150. const int seq = graph->nextSequence();
  151. stack.push(node);
  152. while (!stack.empty()) {
  153. pos = stack.top();
  154. stack.pop();
  155. if (pos == this)
  156. return true;
  157. if (pos == term)
  158. continue;
  159. for (EdgeIterator ei = pos->outgoing(); !ei.end(); ei.next()) {
  160. if (ei.getType() == Edge::BACK || ei.getType() == Edge::DUMMY)
  161. continue;
  162. if (ei.getNode()->visit(seq))
  163. stack.push(ei.getNode());
  164. }
  165. }
  166. return pos == this;
  167. }
  168. class DFSIterator : public Iterator
  169. {
  170. public:
  171. DFSIterator(Graph *graph, const bool preorder)
  172. {
  173. unsigned int seq = graph->nextSequence();
  174. nodes = new Graph::Node * [graph->getSize() + 1];
  175. count = 0;
  176. pos = 0;
  177. nodes[graph->getSize()] = 0;
  178. if (graph->getRoot()) {
  179. graph->getRoot()->visit(seq);
  180. search(graph->getRoot(), preorder, seq);
  181. }
  182. }
  183. ~DFSIterator()
  184. {
  185. if (nodes)
  186. delete[] nodes;
  187. }
  188. void search(Graph::Node *node, const bool preorder, const int sequence)
  189. {
  190. if (preorder)
  191. nodes[count++] = node;
  192. for (Graph::EdgeIterator ei = node->outgoing(); !ei.end(); ei.next())
  193. if (ei.getNode()->visit(sequence))
  194. search(ei.getNode(), preorder, sequence);
  195. if (!preorder)
  196. nodes[count++] = node;
  197. }
  198. virtual bool end() const { return pos >= count; }
  199. virtual void next() { if (pos < count) ++pos; }
  200. virtual void *get() const { return nodes[pos]; }
  201. virtual void reset() { pos = 0; }
  202. protected:
  203. Graph::Node **nodes;
  204. int count;
  205. int pos;
  206. };
  207. IteratorRef Graph::iteratorDFS(bool preorder)
  208. {
  209. return IteratorRef(new DFSIterator(this, preorder));
  210. }
  211. IteratorRef Graph::safeIteratorDFS(bool preorder)
  212. {
  213. return this->iteratorDFS(preorder);
  214. }
  215. class CFGIterator : public Iterator
  216. {
  217. public:
  218. CFGIterator(Graph *graph)
  219. {
  220. nodes = new Graph::Node * [graph->getSize() + 1];
  221. count = 0;
  222. pos = 0;
  223. nodes[graph->getSize()] = 0;
  224. // TODO: argh, use graph->sequence instead of tag and just raise it by > 1
  225. for (IteratorRef it = graph->iteratorDFS(); !it->end(); it->next())
  226. reinterpret_cast<Graph::Node *>(it->get())->tag = 0;
  227. if (graph->getRoot())
  228. search(graph->getRoot(), graph->nextSequence());
  229. }
  230. ~CFGIterator()
  231. {
  232. if (nodes)
  233. delete[] nodes;
  234. }
  235. virtual void *get() const { return nodes[pos]; }
  236. virtual bool end() const { return pos >= count; }
  237. virtual void next() { if (pos < count) ++pos; }
  238. virtual void reset() { pos = 0; }
  239. private:
  240. void search(Graph::Node *node, const int sequence)
  241. {
  242. Stack bb, cross;
  243. bb.push(node);
  244. while (bb.getSize()) {
  245. node = reinterpret_cast<Graph::Node *>(bb.pop().u.p);
  246. assert(node);
  247. if (!node->visit(sequence))
  248. continue;
  249. node->tag = 0;
  250. for (Graph::EdgeIterator ei = node->outgoing(); !ei.end(); ei.next()) {
  251. switch (ei.getType()) {
  252. case Graph::Edge::TREE:
  253. case Graph::Edge::FORWARD:
  254. case Graph::Edge::DUMMY:
  255. if (++(ei.getNode()->tag) == ei.getNode()->incidentCountFwd())
  256. bb.push(ei.getNode());
  257. break;
  258. case Graph::Edge::BACK:
  259. continue;
  260. case Graph::Edge::CROSS:
  261. if (++(ei.getNode()->tag) == 1)
  262. cross.push(ei.getNode());
  263. break;
  264. default:
  265. assert(!"unknown edge kind in CFG");
  266. break;
  267. }
  268. }
  269. nodes[count++] = node;
  270. if (bb.getSize() == 0)
  271. cross.moveTo(bb);
  272. }
  273. }
  274. private:
  275. Graph::Node **nodes;
  276. int count;
  277. int pos;
  278. };
  279. IteratorRef Graph::iteratorCFG()
  280. {
  281. return IteratorRef(new CFGIterator(this));
  282. }
  283. IteratorRef Graph::safeIteratorCFG()
  284. {
  285. return this->iteratorCFG();
  286. }
  287. void Graph::classifyEdges()
  288. {
  289. int seq;
  290. for (IteratorRef it = iteratorDFS(true); !it->end(); it->next()) {
  291. Node *node = reinterpret_cast<Node *>(it->get());
  292. node->visit(0);
  293. node->tag = 0;
  294. }
  295. classifyDFS(root, (seq = 0));
  296. sequence = seq;
  297. }
  298. void Graph::classifyDFS(Node *curr, int& seq)
  299. {
  300. Graph::Edge *edge;
  301. Graph::Node *node;
  302. curr->visit(++seq);
  303. curr->tag = 1;
  304. for (edge = curr->out; edge; edge = edge->next[0]) {
  305. node = edge->target;
  306. if (edge->type == Edge::DUMMY)
  307. continue;
  308. if (node->getSequence() == 0) {
  309. edge->type = Edge::TREE;
  310. classifyDFS(node, seq);
  311. } else
  312. if (node->getSequence() > curr->getSequence()) {
  313. edge->type = Edge::FORWARD;
  314. } else {
  315. edge->type = node->tag ? Edge::BACK : Edge::CROSS;
  316. }
  317. }
  318. for (edge = curr->in; edge; edge = edge->next[1]) {
  319. node = edge->origin;
  320. if (edge->type == Edge::DUMMY)
  321. continue;
  322. if (node->getSequence() == 0) {
  323. edge->type = Edge::TREE;
  324. classifyDFS(node, seq);
  325. } else
  326. if (node->getSequence() > curr->getSequence()) {
  327. edge->type = Edge::FORWARD;
  328. } else {
  329. edge->type = node->tag ? Edge::BACK : Edge::CROSS;
  330. }
  331. }
  332. curr->tag = 0;
  333. }
  334. // @dist is indexed by Node::tag, returns -1 if no path found
  335. int
  336. Graph::findLightestPathWeight(Node *a, Node *b, const std::vector<int> &weight)
  337. {
  338. std::vector<int> path(weight.size(), std::numeric_limits<int>::max());
  339. std::list<Node *> nodeList;
  340. const int seq = nextSequence();
  341. path[a->tag] = 0;
  342. for (Node *c = a; c && c != b;) {
  343. const int p = path[c->tag] + weight[c->tag];
  344. for (EdgeIterator ei = c->outgoing(); !ei.end(); ei.next()) {
  345. Node *t = ei.getNode();
  346. if (t->getSequence() < seq) {
  347. if (path[t->tag] == std::numeric_limits<int>::max())
  348. nodeList.push_front(t);
  349. if (p < path[t->tag])
  350. path[t->tag] = p;
  351. }
  352. }
  353. c->visit(seq);
  354. Node *next = NULL;
  355. for (std::list<Node *>::iterator n = nodeList.begin();
  356. n != nodeList.end(); ++n) {
  357. if (!next || path[(*n)->tag] < path[next->tag])
  358. next = *n;
  359. if ((*n) == c) {
  360. // erase visited
  361. n = nodeList.erase(n);
  362. --n;
  363. }
  364. }
  365. c = next;
  366. }
  367. if (path[b->tag] == std::numeric_limits<int>::max())
  368. return -1;
  369. return path[b->tag];
  370. }
  371. } // namespace nv50_ir