radeon: enable Hyper-Z on r600g and radeonsi by default
[mesa.git] / src / gallium / drivers / nouveau / 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 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
23 #include "codegen/nv50_ir.h"
24
25 namespace nv50_ir {
26
27 Function::Function(Program *p, const char *fnName, uint32_t label)
28 : call(this),
29 label(label),
30 name(fnName),
31 prog(p)
32 {
33 cfgExit = NULL;
34 domTree = NULL;
35
36 bbArray = NULL;
37 bbCount = 0;
38 loopNestingBound = 0;
39 regClobberMax = 0;
40
41 binPos = 0;
42 binSize = 0;
43
44 stackPtr = NULL;
45 tlsBase = 0;
46 tlsSize = 0;
47
48 prog->add(this, id);
49 }
50
51 Function::~Function()
52 {
53 prog->del(this, id);
54
55 if (domTree)
56 delete domTree;
57 if (bbArray)
58 delete[] bbArray;
59
60 // clear value refs and defs
61 ins.clear();
62 outs.clear();
63
64 for (ArrayList::Iterator it = allInsns.iterator(); !it.end(); it.next())
65 delete_Instruction(prog, reinterpret_cast<Instruction *>(it.get()));
66
67 for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next())
68 delete_Value(prog, reinterpret_cast<LValue *>(it.get()));
69
70 for (ArrayList::Iterator BBs = allBBlocks.iterator(); !BBs.end(); BBs.next())
71 delete reinterpret_cast<BasicBlock *>(BBs.get());
72 }
73
74 BasicBlock::BasicBlock(Function *fn) : cfg(this), dom(this), func(fn)
75 {
76 program = func->getProgram();
77
78 joinAt = phi = entry = exit = NULL;
79
80 numInsns = 0;
81 binPos = 0;
82 binSize = 0;
83
84 explicitCont = false;
85
86 func->add(this, this->id);
87 }
88
89 BasicBlock::~BasicBlock()
90 {
91 // nothing yet
92 }
93
94 BasicBlock *
95 BasicBlock::clone(ClonePolicy<Function>& pol) const
96 {
97 BasicBlock *bb = new BasicBlock(pol.context());
98
99 pol.set(this, bb);
100
101 for (Instruction *i = getFirst(); i; i = i->next)
102 bb->insertTail(i->clone(pol));
103
104 pol.context()->cfg.insert(&bb->cfg);
105
106 for (Graph::EdgeIterator it = cfg.outgoing(); !it.end(); it.next()) {
107 BasicBlock *obb = BasicBlock::get(it.getNode());
108 bb->cfg.attach(&pol.get(obb)->cfg, it.getType());
109 }
110
111 return bb;
112 }
113
114 BasicBlock *
115 BasicBlock::idom() const
116 {
117 Graph::Node *dn = dom.parent();
118 return dn ? BasicBlock::get(dn) : NULL;
119 }
120
121 void
122 BasicBlock::insertHead(Instruction *inst)
123 {
124 assert(inst->next == 0 && inst->prev == 0);
125
126 if (inst->op == OP_PHI) {
127 if (phi) {
128 insertBefore(phi, inst);
129 } else {
130 if (entry) {
131 insertBefore(entry, inst);
132 } else {
133 assert(!exit);
134 phi = exit = inst;
135 inst->bb = this;
136 ++numInsns;
137 }
138 }
139 } else {
140 if (entry) {
141 insertBefore(entry, inst);
142 } else {
143 if (phi) {
144 insertAfter(exit, inst); // after last phi
145 } else {
146 assert(!exit);
147 entry = exit = inst;
148 inst->bb = this;
149 ++numInsns;
150 }
151 }
152 }
153 }
154
155 void
156 BasicBlock::insertTail(Instruction *inst)
157 {
158 assert(inst->next == 0 && inst->prev == 0);
159
160 if (inst->op == OP_PHI) {
161 if (entry) {
162 insertBefore(entry, inst);
163 } else
164 if (exit) {
165 assert(phi);
166 insertAfter(exit, inst);
167 } else {
168 assert(!phi);
169 phi = exit = inst;
170 inst->bb = this;
171 ++numInsns;
172 }
173 } else {
174 if (exit) {
175 insertAfter(exit, inst);
176 } else {
177 assert(!phi);
178 entry = exit = inst;
179 inst->bb = this;
180 ++numInsns;
181 }
182 }
183 }
184
185 void
186 BasicBlock::insertBefore(Instruction *q, Instruction *p)
187 {
188 assert(p && q);
189
190 assert(p->next == 0 && p->prev == 0);
191
192 if (q == entry) {
193 if (p->op == OP_PHI) {
194 if (!phi)
195 phi = p;
196 } else {
197 entry = p;
198 }
199 } else
200 if (q == phi) {
201 assert(p->op == OP_PHI);
202 phi = p;
203 }
204
205 p->next = q;
206 p->prev = q->prev;
207 if (p->prev)
208 p->prev->next = p;
209 q->prev = p;
210
211 p->bb = this;
212 ++numInsns;
213 }
214
215 void
216 BasicBlock::insertAfter(Instruction *p, Instruction *q)
217 {
218 assert(p && q);
219 assert(q->op != OP_PHI || p->op == OP_PHI);
220
221 assert(q->next == 0 && q->prev == 0);
222
223 if (p == exit)
224 exit = q;
225 if (p->op == OP_PHI && q->op != OP_PHI)
226 entry = q;
227
228 q->prev = p;
229 q->next = p->next;
230 if (q->next)
231 q->next->prev = q;
232 p->next = q;
233
234 q->bb = this;
235 ++numInsns;
236 }
237
238 void
239 BasicBlock::remove(Instruction *insn)
240 {
241 assert(insn->bb == this);
242
243 if (insn->prev)
244 insn->prev->next = insn->next;
245
246 if (insn->next)
247 insn->next->prev = insn->prev;
248 else
249 exit = insn->prev;
250
251 if (insn == entry) {
252 if (insn->next)
253 entry = insn->next;
254 else
255 if (insn->prev && insn->prev->op != OP_PHI)
256 entry = insn->prev;
257 else
258 entry = NULL;
259 }
260
261 if (insn == phi)
262 phi = (insn->next && insn->next->op == OP_PHI) ? insn->next : 0;
263
264 --numInsns;
265 insn->bb = NULL;
266 insn->next =
267 insn->prev = NULL;
268 }
269
270 void BasicBlock::permuteAdjacent(Instruction *a, Instruction *b)
271 {
272 assert(a->bb == b->bb);
273
274 if (a->next != b) {
275 Instruction *i = a;
276 a = b;
277 b = i;
278 }
279 assert(a->next == b);
280 assert(a->op != OP_PHI && b->op != OP_PHI);
281
282 if (b == exit)
283 exit = a;
284 if (a == entry)
285 entry = b;
286
287 b->prev = a->prev;
288 a->next = b->next;
289 b->next = a;
290 a->prev = b;
291
292 if (b->prev)
293 b->prev->next = b;
294 if (a->prev)
295 a->next->prev = a;
296 }
297
298 void
299 BasicBlock::splitCommon(Instruction *insn, BasicBlock *bb, bool attach)
300 {
301 bb->entry = insn;
302
303 if (insn) {
304 exit = insn->prev;
305 insn->prev = NULL;
306 }
307
308 if (exit)
309 exit->next = NULL;
310 else
311 entry = NULL;
312
313 while (!cfg.outgoing(true).end()) {
314 Graph::Edge *e = cfg.outgoing(true).getEdge();
315 bb->cfg.attach(e->getTarget(), e->getType());
316 this->cfg.detach(e->getTarget());
317 }
318
319 for (; insn; insn = insn->next) {
320 this->numInsns--;
321 bb->numInsns++;
322 insn->bb = bb;
323 bb->exit = insn;
324 }
325 if (attach)
326 this->cfg.attach(&bb->cfg, Graph::Edge::TREE);
327 }
328
329 BasicBlock *
330 BasicBlock::splitBefore(Instruction *insn, bool attach)
331 {
332 BasicBlock *bb = new BasicBlock(func);
333 assert(!insn || insn->op != OP_PHI);
334
335 splitCommon(insn, bb, attach);
336 return bb;
337 }
338
339 BasicBlock *
340 BasicBlock::splitAfter(Instruction *insn, bool attach)
341 {
342 BasicBlock *bb = new BasicBlock(func);
343 assert(!insn || insn->op != OP_PHI);
344
345 bb->joinAt = joinAt;
346 joinAt = NULL;
347
348 splitCommon(insn ? insn->next : NULL, bb, attach);
349 return bb;
350 }
351
352 bool
353 BasicBlock::dominatedBy(BasicBlock *that)
354 {
355 Graph::Node *bn = &that->dom;
356 Graph::Node *dn = &this->dom;
357
358 while (dn && dn != bn)
359 dn = dn->parent();
360
361 return dn != NULL;
362 }
363
364 unsigned int
365 BasicBlock::initiatesSimpleConditional() const
366 {
367 Graph::Node *out[2];
368 int n;
369 Graph::Edge::Type eR;
370
371 if (cfg.outgoingCount() != 2) // -> if and -> else/endif
372 return false;
373
374 n = 0;
375 for (Graph::EdgeIterator ei = cfg.outgoing(); !ei.end(); ei.next())
376 out[n++] = ei.getNode();
377 eR = out[1]->outgoing().getType();
378
379 // IF block is out edge to the right
380 if (eR == Graph::Edge::CROSS || eR == Graph::Edge::BACK)
381 return 0x2;
382
383 if (out[1]->outgoingCount() != 1) // 0 is IF { RET; }, >1 is more divergence
384 return 0x0;
385 // do they reconverge immediately ?
386 if (out[1]->outgoing().getNode() == out[0])
387 return 0x1;
388 if (out[0]->outgoingCount() == 1)
389 if (out[0]->outgoing().getNode() == out[1]->outgoing().getNode())
390 return 0x3;
391
392 return 0x0;
393 }
394
395 bool
396 Function::setEntry(BasicBlock *bb)
397 {
398 if (cfg.getRoot())
399 return false;
400 cfg.insert(&bb->cfg);
401 return true;
402 }
403
404 bool
405 Function::setExit(BasicBlock *bb)
406 {
407 if (cfgExit)
408 return false;
409 cfgExit = &bb->cfg;
410 return true;
411 }
412
413 unsigned int
414 Function::orderInstructions(ArrayList &result)
415 {
416 result.clear();
417
418 for (IteratorRef it = cfg.iteratorCFG(); !it->end(); it->next()) {
419 BasicBlock *bb =
420 BasicBlock::get(reinterpret_cast<Graph::Node *>(it->get()));
421
422 for (Instruction *insn = bb->getFirst(); insn; insn = insn->next)
423 result.insert(insn, insn->serial);
424 }
425
426 return result.getSize();
427 }
428
429 void
430 Function::buildLiveSets()
431 {
432 for (unsigned i = 0; i <= loopNestingBound; ++i)
433 buildLiveSetsPreSSA(BasicBlock::get(cfg.getRoot()), cfg.nextSequence());
434
435 for (ArrayList::Iterator bi = allBBlocks.iterator(); !bi.end(); bi.next())
436 BasicBlock::get(bi)->liveSet.marker = false;
437 }
438
439 void
440 Function::buildDefSets()
441 {
442 for (unsigned i = 0; i <= loopNestingBound; ++i)
443 buildDefSetsPreSSA(BasicBlock::get(cfgExit), cfg.nextSequence());
444
445 for (ArrayList::Iterator bi = allBBlocks.iterator(); !bi.end(); bi.next())
446 BasicBlock::get(bi)->liveSet.marker = false;
447 }
448
449 bool
450 Pass::run(Program *prog, bool ordered, bool skipPhi)
451 {
452 this->prog = prog;
453 err = false;
454 return doRun(prog, ordered, skipPhi);
455 }
456
457 bool
458 Pass::doRun(Program *prog, bool ordered, bool skipPhi)
459 {
460 for (IteratorRef it = prog->calls.iteratorDFS(false);
461 !it->end(); it->next()) {
462 Graph::Node *n = reinterpret_cast<Graph::Node *>(it->get());
463 if (!doRun(Function::get(n), ordered, skipPhi))
464 return false;
465 }
466 return !err;
467 }
468
469 bool
470 Pass::run(Function *func, bool ordered, bool skipPhi)
471 {
472 prog = func->getProgram();
473 err = false;
474 return doRun(func, ordered, skipPhi);
475 }
476
477 bool
478 Pass::doRun(Function *func, bool ordered, bool skipPhi)
479 {
480 IteratorRef bbIter;
481 BasicBlock *bb;
482 Instruction *insn, *next;
483
484 this->func = func;
485 if (!visit(func))
486 return false;
487
488 bbIter = ordered ? func->cfg.iteratorCFG() : func->cfg.iteratorDFS();
489
490 for (; !bbIter->end(); bbIter->next()) {
491 bb = BasicBlock::get(reinterpret_cast<Graph::Node *>(bbIter->get()));
492 if (!visit(bb))
493 break;
494 for (insn = skipPhi ? bb->getEntry() : bb->getFirst(); insn != NULL;
495 insn = next) {
496 next = insn->next;
497 if (!visit(insn))
498 break;
499 }
500 }
501
502 return !err;
503 }
504
505 void
506 Function::printCFGraph(const char *filePath)
507 {
508 FILE *out = fopen(filePath, "a");
509 if (!out) {
510 ERROR("failed to open file: %s\n", filePath);
511 return;
512 }
513 INFO("printing control flow graph to: %s\n", filePath);
514
515 fprintf(out, "digraph G {\n");
516
517 for (IteratorRef it = cfg.iteratorDFS(); !it->end(); it->next()) {
518 BasicBlock *bb = BasicBlock::get(
519 reinterpret_cast<Graph::Node *>(it->get()));
520 int idA = bb->getId();
521 for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {
522 int idB = BasicBlock::get(ei.getNode())->getId();
523 switch (ei.getType()) {
524 case Graph::Edge::TREE:
525 fprintf(out, "\t%i -> %i;\n", idA, idB);
526 break;
527 case Graph::Edge::FORWARD:
528 fprintf(out, "\t%i -> %i [color=green];\n", idA, idB);
529 break;
530 case Graph::Edge::CROSS:
531 fprintf(out, "\t%i -> %i [color=red];\n", idA, idB);
532 break;
533 case Graph::Edge::BACK:
534 fprintf(out, "\t%i -> %i;\n", idA, idB);
535 break;
536 case Graph::Edge::DUMMY:
537 fprintf(out, "\t%i -> %i [style=dotted];\n", idA, idB);
538 break;
539 default:
540 assert(0);
541 break;
542 }
543 }
544 }
545
546 fprintf(out, "}\n");
547 fclose(out);
548 }
549
550 } // namespace nv50_ir