2
* Copyright 2011 Christoph Bumiller
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:
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
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.
23
#include "codegen/nv50_ir.h"
27
Function::Function(Program *p, const char *fnName, uint32_t label)
60
// clear value refs and defs
64
for (ArrayList::Iterator it = allInsns.iterator(); !it.end(); it.next())
65
delete_Instruction(prog, reinterpret_cast<Instruction *>(it.get()));
67
for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next())
68
delete_Value(prog, reinterpret_cast<LValue *>(it.get()));
70
for (ArrayList::Iterator BBs = allBBlocks.iterator(); !BBs.end(); BBs.next())
71
delete reinterpret_cast<BasicBlock *>(BBs.get());
74
BasicBlock::BasicBlock(Function *fn) : cfg(this), dom(this), func(fn)
76
program = func->getProgram();
78
joinAt = phi = entry = exit = NULL;
86
func->add(this, this->id);
89
BasicBlock::~BasicBlock()
95
BasicBlock::clone(ClonePolicy<Function>& pol) const
97
BasicBlock *bb = new BasicBlock(pol.context());
101
for (Instruction *i = getFirst(); i; i = i->next)
102
bb->insertTail(i->clone(pol));
104
pol.context()->cfg.insert(&bb->cfg);
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());
115
BasicBlock::idom() const
117
Graph::Node *dn = dom.parent();
118
return dn ? BasicBlock::get(dn) : NULL;
122
BasicBlock::insertHead(Instruction *inst)
124
assert(inst->next == 0 && inst->prev == 0);
126
if (inst->op == OP_PHI) {
128
insertBefore(phi, inst);
131
insertBefore(entry, inst);
141
insertBefore(entry, inst);
144
insertAfter(exit, inst); // after last phi
156
BasicBlock::insertTail(Instruction *inst)
158
assert(inst->next == 0 && inst->prev == 0);
160
if (inst->op == OP_PHI) {
162
insertBefore(entry, inst);
166
insertAfter(exit, inst);
175
insertAfter(exit, inst);
186
BasicBlock::insertBefore(Instruction *q, Instruction *p)
190
assert(p->next == 0 && p->prev == 0);
193
if (p->op == OP_PHI) {
201
assert(p->op == OP_PHI);
216
BasicBlock::insertAfter(Instruction *p, Instruction *q)
219
assert(q->op != OP_PHI || p->op == OP_PHI);
221
assert(q->next == 0 && q->prev == 0);
225
if (p->op == OP_PHI && q->op != OP_PHI)
239
BasicBlock::remove(Instruction *insn)
241
assert(insn->bb == this);
244
insn->prev->next = insn->next;
247
insn->next->prev = insn->prev;
255
if (insn->prev && insn->prev->op != OP_PHI)
262
phi = (insn->next && insn->next->op == OP_PHI) ? insn->next : 0;
270
void BasicBlock::permuteAdjacent(Instruction *a, Instruction *b)
272
assert(a->bb == b->bb);
279
assert(a->next == b);
280
assert(a->op != OP_PHI && b->op != OP_PHI);
299
BasicBlock::splitCommon(Instruction *insn, BasicBlock *bb, bool attach)
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());
319
for (; insn; insn = insn->next) {
326
this->cfg.attach(&bb->cfg, Graph::Edge::TREE);
330
BasicBlock::splitBefore(Instruction *insn, bool attach)
332
BasicBlock *bb = new BasicBlock(func);
333
assert(!insn || insn->op != OP_PHI);
338
splitCommon(insn, bb, attach);
343
BasicBlock::splitAfter(Instruction *insn, bool attach)
345
BasicBlock *bb = new BasicBlock(func);
346
assert(!insn || insn->op != OP_PHI);
351
splitCommon(insn ? insn->next : NULL, bb, attach);
356
BasicBlock::dominatedBy(BasicBlock *that)
358
Graph::Node *bn = &that->dom;
359
Graph::Node *dn = &this->dom;
361
while (dn && dn != bn)
368
BasicBlock::initiatesSimpleConditional() const
372
Graph::Edge::Type eR;
374
if (cfg.outgoingCount() != 2) // -> if and -> else/endif
378
for (Graph::EdgeIterator ei = cfg.outgoing(); !ei.end(); ei.next())
379
out[n++] = ei.getNode();
380
eR = out[1]->outgoing().getType();
382
// IF block is out edge to the right
383
if (eR == Graph::Edge::CROSS || eR == Graph::Edge::BACK)
386
if (out[1]->outgoingCount() != 1) // 0 is IF { RET; }, >1 is more divergence
388
// do they reconverge immediately ?
389
if (out[1]->outgoing().getNode() == out[0])
391
if (out[0]->outgoingCount() == 1)
392
if (out[0]->outgoing().getNode() == out[1]->outgoing().getNode())
399
Function::setEntry(BasicBlock *bb)
403
cfg.insert(&bb->cfg);
408
Function::setExit(BasicBlock *bb)
417
Function::orderInstructions(ArrayList &result)
421
for (IteratorRef it = cfg.iteratorCFG(); !it->end(); it->next()) {
423
BasicBlock::get(reinterpret_cast<Graph::Node *>(it->get()));
425
for (Instruction *insn = bb->getFirst(); insn; insn = insn->next)
426
result.insert(insn, insn->serial);
429
return result.getSize();
433
Function::buildLiveSets()
435
for (unsigned i = 0; i <= loopNestingBound; ++i)
436
buildLiveSetsPreSSA(BasicBlock::get(cfg.getRoot()), cfg.nextSequence());
438
for (ArrayList::Iterator bi = allBBlocks.iterator(); !bi.end(); bi.next())
439
BasicBlock::get(bi)->liveSet.marker = false;
443
Function::buildDefSets()
445
for (unsigned i = 0; i <= loopNestingBound; ++i)
446
buildDefSetsPreSSA(BasicBlock::get(cfgExit), cfg.nextSequence());
448
for (ArrayList::Iterator bi = allBBlocks.iterator(); !bi.end(); bi.next())
449
BasicBlock::get(bi)->liveSet.marker = false;
453
Pass::run(Program *prog, bool ordered, bool skipPhi)
457
return doRun(prog, ordered, skipPhi);
461
Pass::doRun(Program *prog, bool ordered, bool skipPhi)
463
for (IteratorRef it = prog->calls.iteratorDFS(false);
464
!it->end(); it->next()) {
465
Graph::Node *n = reinterpret_cast<Graph::Node *>(it->get());
466
if (!doRun(Function::get(n), ordered, skipPhi))
473
Pass::run(Function *func, bool ordered, bool skipPhi)
475
prog = func->getProgram();
477
return doRun(func, ordered, skipPhi);
481
Pass::doRun(Function *func, bool ordered, bool skipPhi)
485
Instruction *insn, *next;
491
bbIter = ordered ? func->cfg.iteratorCFG() : func->cfg.iteratorDFS();
493
for (; !bbIter->end(); bbIter->next()) {
494
bb = BasicBlock::get(reinterpret_cast<Graph::Node *>(bbIter->get()));
497
for (insn = skipPhi ? bb->getEntry() : bb->getFirst(); insn != NULL;
509
Function::printCFGraph(const char *filePath)
511
FILE *out = fopen(filePath, "a");
513
ERROR("failed to open file: %s\n", filePath);
516
INFO("printing control flow graph to: %s\n", filePath);
518
fprintf(out, "digraph G {\n");
520
for (IteratorRef it = cfg.iteratorDFS(); !it->end(); it->next()) {
521
BasicBlock *bb = BasicBlock::get(
522
reinterpret_cast<Graph::Node *>(it->get()));
523
int idA = bb->getId();
524
for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {
525
int idB = BasicBlock::get(ei.getNode())->getId();
526
switch (ei.getType()) {
527
case Graph::Edge::TREE:
528
fprintf(out, "\t%i -> %i;\n", idA, idB);
530
case Graph::Edge::FORWARD:
531
fprintf(out, "\t%i -> %i [color=green];\n", idA, idB);
533
case Graph::Edge::CROSS:
534
fprintf(out, "\t%i -> %i [color=red];\n", idA, idB);
536
case Graph::Edge::BACK:
537
fprintf(out, "\t%i -> %i;\n", idA, idB);
550
} // namespace nv50_ir