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