nv50/ir: add missing license headers
[mesa.git] / src / gallium / drivers / nv50 / codegen / nv50_ir_bb.cpp
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 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
20 * SOFTWARE.
21 */
22
23 #include "nv50_ir.h"
24
25 namespace nv50_ir {
26
27 Function::Function(Program *p, const char *fnName)
28 : call(this),
29 name(fnName),
30 prog(p)
31 {
32 cfgExit = NULL;
33 domTree = NULL;
34
35 bbArray = NULL;
36 bbCount = 0;
37 loopNestingBound = 0;
38 regClobberMax = 0;
39
40 binPos = 0;
41 binSize = 0;
42
43 prog->add(this, id);
44 }
45
46 Function::~Function()
47 {
48 if (domTree)
49 delete domTree;
50 if (bbArray)
51 delete[] bbArray;
52
53 for (ArrayList::Iterator BBs = allBBlocks.iterator(); !BBs.end(); BBs.next())
54 delete reinterpret_cast<BasicBlock *>(BBs.get());
55 }
56
57 BasicBlock::BasicBlock(Function *fn) : cfg(this), dom(this), func(fn)
58 {
59 program = func->getProgram();
60
61 joinAt = phi = entry = exit = NULL;
62
63 numInsns = 0;
64 binPos = 0;
65 binSize = 0;
66
67 explicitCont = false;
68
69 func->add(this, this->id);
70 }
71
72 BasicBlock::~BasicBlock()
73 {
74 // nothing yet
75 }
76
77 BasicBlock *
78 BasicBlock::idom() const
79 {
80 Graph::Node *dn = dom.parent();
81 return dn ? BasicBlock::get(dn) : NULL;
82 }
83
84 void
85 BasicBlock::insertHead(Instruction *inst)
86 {
87 assert(inst->next == 0 && inst->prev == 0);
88
89 if (inst->op == OP_PHI) {
90 if (phi) {
91 insertBefore(phi, inst);
92 } else {
93 if (entry) {
94 insertBefore(entry, phi);
95 } else {
96 assert(!exit);
97 phi = exit = inst;
98 inst->bb = this;
99 ++numInsns;
100 }
101 }
102 } else {
103 if (entry) {
104 insertBefore(entry, inst);
105 } else {
106 if (phi) {
107 insertAfter(phi, inst);
108 } else {
109 assert(!exit);
110 entry = exit = inst;
111 inst->bb = this;
112 ++numInsns;
113 }
114 }
115 }
116 }
117
118 void
119 BasicBlock::insertTail(Instruction *inst)
120 {
121 assert(inst->next == 0 && inst->prev == 0);
122
123 if (inst->op == OP_PHI) {
124 if (entry) {
125 insertBefore(entry, inst);
126 } else
127 if (exit) {
128 assert(phi);
129 insertAfter(exit, inst);
130 } else {
131 assert(!phi);
132 phi = exit = inst;
133 inst->bb = this;
134 ++numInsns;
135 }
136 } else {
137 if (exit) {
138 insertAfter(exit, inst);
139 } else {
140 assert(!phi);
141 entry = exit = inst;
142 inst->bb = this;
143 ++numInsns;
144 }
145 }
146 }
147
148 void
149 BasicBlock::insertBefore(Instruction *q, Instruction *p)
150 {
151 assert(p && q);
152
153 assert(p->next == 0 && p->prev == 0);
154
155 if (q == entry) {
156 if (p->op == OP_PHI) {
157 if (!phi)
158 phi = p;
159 } else {
160 entry = p;
161 }
162 } else
163 if (q == phi) {
164 assert(p->op == OP_PHI);
165 phi = p;
166 }
167
168 p->next = q;
169 p->prev = q->prev;
170 if (p->prev)
171 p->prev->next = p;
172 q->prev = p;
173
174 p->bb = this;
175 ++numInsns;
176 }
177
178 void
179 BasicBlock::insertAfter(Instruction *p, Instruction *q)
180 {
181 assert(p && q);
182 assert(q->op != OP_PHI || p->op == OP_PHI);
183
184 assert(q->next == 0 && q->prev == 0);
185
186 if (p == exit)
187 exit = q;
188 if (p->op == OP_PHI && q->op != OP_PHI)
189 entry = q;
190
191 q->prev = p;
192 q->next = p->next;
193 if (q->next)
194 q->next->prev = q;
195 p->next = q;
196
197 q->bb = this;
198 ++numInsns;
199 }
200
201 void
202 BasicBlock::remove(Instruction *insn)
203 {
204 assert(insn->bb == this);
205
206 if (insn->prev)
207 insn->prev->next = insn->next;
208
209 if (insn->next)
210 insn->next->prev = insn->prev;
211 else
212 exit = insn->prev;
213
214 if (insn == entry)
215 entry = insn->next ? insn->next : insn->prev;
216
217 if (insn == phi)
218 phi = (insn->next && insn->next->op == OP_PHI) ? insn->next : 0;
219
220 --numInsns;
221 insn->bb = NULL;
222 insn->next =
223 insn->prev = NULL;
224 }
225
226 void BasicBlock::permuteAdjacent(Instruction *a, Instruction *b)
227 {
228 assert(a->bb == b->bb);
229
230 if (a->next != b) {
231 Instruction *i = a;
232 a = b;
233 b = i;
234 }
235 assert(a->next == b);
236 assert(a->op != OP_PHI && b->op != OP_PHI);
237
238 if (b == exit)
239 exit = a;
240 if (a == entry)
241 entry = b;
242
243 b->prev = a->prev;
244 a->next = b->next;
245 b->next = a;
246 a->prev = b;
247
248 if (b->prev)
249 b->prev->next = b;
250 if (a->prev)
251 a->next->prev = a;
252 }
253
254 bool
255 BasicBlock::dominatedBy(BasicBlock *that)
256 {
257 Graph::Node *bn = &that->dom;
258 Graph::Node *dn = &this->dom;
259
260 while (dn && dn != bn)
261 dn = dn->parent();
262
263 return dn != NULL;
264 }
265
266 unsigned int
267 BasicBlock::initiatesSimpleConditional() const
268 {
269 Graph::Node *out[2];
270 int n;
271 Graph::Edge::Type eR;
272
273 if (cfg.outgoingCount() != 2) // -> if and -> else/endif
274 return false;
275
276 n = 0;
277 for (Graph::EdgeIterator ei = cfg.outgoing(); !ei.end(); ei.next())
278 out[n++] = ei.getNode();
279 eR = out[1]->outgoing().getType();
280
281 // IF block is out edge to the right
282 if (eR == Graph::Edge::CROSS || eR == Graph::Edge::BACK)
283 return 0x2;
284
285 if (out[1]->outgoingCount() != 1) // 0 is IF { RET; }, >1 is more divergence
286 return 0x0;
287 // do they reconverge immediately ?
288 if (out[1]->outgoing().getNode() == out[0])
289 return 0x1;
290 if (out[0]->outgoingCount() == 1)
291 if (out[0]->outgoing().getNode() == out[1]->outgoing().getNode())
292 return 0x3;
293
294 return 0x0;
295 }
296
297 bool
298 Function::setEntry(BasicBlock *bb)
299 {
300 if (cfg.getRoot())
301 return false;
302 cfg.insert(&bb->cfg);
303 return true;
304 }
305
306 bool
307 Function::setExit(BasicBlock *bb)
308 {
309 if (cfgExit)
310 return false;
311 cfgExit = &bb->cfg;
312 return true;
313 }
314
315 unsigned int
316 Function::orderInstructions(ArrayList &result)
317 {
318 Iterator *iter;
319 for (iter = cfg.iteratorCFG(); !iter->end(); iter->next())
320 for (Instruction *insn = BasicBlock::get(*iter)->getFirst();
321 insn; insn = insn->next)
322 result.insert(insn, insn->serial);
323 cfg.putIterator(iter);
324 return result.getSize();
325 }
326
327 bool
328 Pass::run(Program *prog, bool ordered, bool skipPhi)
329 {
330 this->prog = prog;
331 err = false;
332 return doRun(prog, ordered, skipPhi);
333 }
334
335 bool
336 Pass::doRun(Program *prog, bool ordered, bool skipPhi)
337 {
338 for (ArrayList::Iterator fi = prog->allFuncs.iterator();
339 !fi.end(); fi.next()) {
340 Function *fn = reinterpret_cast<Function *>(fi.get());
341 if (!doRun(fn, ordered, skipPhi))
342 return false;
343 }
344 return !err;
345 }
346
347 bool
348 Pass::run(Function *func, bool ordered, bool skipPhi)
349 {
350 prog = func->getProgram();
351 err = false;
352 return doRun(func, ordered, skipPhi);
353 }
354
355 bool
356 Pass::doRun(Function *func, bool ordered, bool skipPhi)
357 {
358 Iterator *bbIter;
359 BasicBlock *bb;
360 Instruction *insn, *next;
361
362 this->func = func;
363 if (!visit(func))
364 return false;
365
366 bbIter = ordered ? func->cfg.iteratorCFG() : func->cfg.iteratorDFS();
367
368 for (; !bbIter->end(); bbIter->next()) {
369 bb = BasicBlock::get(reinterpret_cast<Graph::Node *>(bbIter->get()));
370 if (!visit(bb))
371 break;
372 for (insn = skipPhi ? bb->getEntry() : bb->getFirst(); insn != NULL;
373 insn = next) {
374 next = insn->next;
375 if (!visit(insn))
376 break;
377 }
378 }
379 func->cfg.putIterator(bbIter);
380 return !err;
381 }
382
383 void
384 Function::printCFGraph(const char *filePath)
385 {
386 FILE *out = fopen(filePath, "a");
387 if (!out) {
388 ERROR("failed to open file: %s\n", filePath);
389 return;
390 }
391 INFO("printing control flow graph to: %s\n", filePath);
392
393 fprintf(out, "digraph G {\n");
394
395 Iterator *iter;
396 for (iter = cfg.iteratorDFS(); !iter->end(); iter->next()) {
397 BasicBlock *bb = BasicBlock::get(
398 reinterpret_cast<Graph::Node *>(iter->get()));
399 int idA = bb->getId();
400 for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {
401 int idB = BasicBlock::get(ei.getNode())->getId();
402 switch (ei.getType()) {
403 case Graph::Edge::TREE:
404 fprintf(out, "\t%i -> %i;\n", idA, idB);
405 break;
406 case Graph::Edge::FORWARD:
407 fprintf(out, "\t%i -> %i [color=green];\n", idA, idB);
408 break;
409 case Graph::Edge::CROSS:
410 fprintf(out, "\t%i -> %i [color=red];\n", idA, idB);
411 break;
412 case Graph::Edge::BACK:
413 fprintf(out, "\t%i -> %i;\n", idA, idB);
414 break;
415 case Graph::Edge::DUMMY:
416 fprintf(out, "\t%i -> %i [style=dotted];\n", idA, idB);
417 break;
418 default:
419 assert(0);
420 break;
421 }
422 }
423 }
424 cfg.putIterator(iter);
425
426 fprintf(out, "}\n");
427 fclose(out);
428 }
429
430 } // namespace nv50_ir