Path: blob/21.2-virgl/src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp
4574 views
/*1* Copyright 2011 Christoph Bumiller2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*/2122#include "codegen/nv50_ir.h"2324namespace nv50_ir {2526Function::Function(Program *p, const char *fnName, uint32_t label)27: call(this),28label(label),29name(fnName),30prog(p)31{32cfgExit = NULL;33domTree = NULL;3435bbArray = NULL;36bbCount = 0;37loopNestingBound = 0;38regClobberMax = 0;3940binPos = 0;41binSize = 0;4243stackPtr = NULL;44tlsBase = 0;45tlsSize = 0;4647prog->add(this, id);48}4950Function::~Function()51{52prog->del(this, id);5354if (domTree)55delete domTree;56if (bbArray)57delete[] bbArray;5859// clear value refs and defs60ins.clear();61outs.clear();6263for (ArrayList::Iterator it = allInsns.iterator(); !it.end(); it.next())64delete_Instruction(prog, reinterpret_cast<Instruction *>(it.get()));6566for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next())67delete_Value(prog, reinterpret_cast<LValue *>(it.get()));6869for (ArrayList::Iterator BBs = allBBlocks.iterator(); !BBs.end(); BBs.next())70delete reinterpret_cast<BasicBlock *>(BBs.get());71}7273BasicBlock::BasicBlock(Function *fn) : cfg(this), dom(this), func(fn)74{75program = func->getProgram();7677joinAt = phi = entry = exit = NULL;7879numInsns = 0;80binPos = 0;81binSize = 0;8283explicitCont = false;8485func->add(this, this->id);86}8788BasicBlock::~BasicBlock()89{90// nothing yet91}9293BasicBlock *94BasicBlock::clone(ClonePolicy<Function>& pol) const95{96BasicBlock *bb = new BasicBlock(pol.context());9798pol.set(this, bb);99100for (Instruction *i = getFirst(); i; i = i->next)101bb->insertTail(i->clone(pol));102103pol.context()->cfg.insert(&bb->cfg);104105for (Graph::EdgeIterator it = cfg.outgoing(); !it.end(); it.next()) {106BasicBlock *obb = BasicBlock::get(it.getNode());107bb->cfg.attach(&pol.get(obb)->cfg, it.getType());108}109110return bb;111}112113BasicBlock *114BasicBlock::idom() const115{116Graph::Node *dn = dom.parent();117return dn ? BasicBlock::get(dn) : NULL;118}119120void121BasicBlock::insertHead(Instruction *inst)122{123assert(inst->next == 0 && inst->prev == 0);124125if (inst->op == OP_PHI) {126if (phi) {127insertBefore(phi, inst);128} else {129if (entry) {130insertBefore(entry, inst);131} else {132assert(!exit);133phi = exit = inst;134inst->bb = this;135++numInsns;136}137}138} else {139if (entry) {140insertBefore(entry, inst);141} else {142if (phi) {143insertAfter(exit, inst); // after last phi144} else {145assert(!exit);146entry = exit = inst;147inst->bb = this;148++numInsns;149}150}151}152}153154void155BasicBlock::insertTail(Instruction *inst)156{157assert(inst->next == 0 && inst->prev == 0);158159if (inst->op == OP_PHI) {160if (entry) {161insertBefore(entry, inst);162} else163if (exit) {164assert(phi);165insertAfter(exit, inst);166} else {167assert(!phi);168phi = exit = inst;169inst->bb = this;170++numInsns;171}172} else {173if (exit) {174insertAfter(exit, inst);175} else {176assert(!phi);177entry = exit = inst;178inst->bb = this;179++numInsns;180}181}182}183184void185BasicBlock::insertBefore(Instruction *q, Instruction *p)186{187assert(p && q);188189assert(p->next == 0 && p->prev == 0);190191if (q == entry) {192if (p->op == OP_PHI) {193if (!phi)194phi = p;195} else {196entry = p;197}198} else199if (q == phi) {200assert(p->op == OP_PHI);201phi = p;202}203204p->next = q;205p->prev = q->prev;206if (p->prev)207p->prev->next = p;208q->prev = p;209210p->bb = this;211++numInsns;212}213214void215BasicBlock::insertAfter(Instruction *p, Instruction *q)216{217assert(p && q);218assert(q->op != OP_PHI || p->op == OP_PHI);219220assert(q->next == 0 && q->prev == 0);221222if (p == exit)223exit = q;224if (p->op == OP_PHI && q->op != OP_PHI)225entry = q;226227q->prev = p;228q->next = p->next;229if (q->next)230q->next->prev = q;231p->next = q;232233q->bb = this;234++numInsns;235}236237void238BasicBlock::remove(Instruction *insn)239{240assert(insn->bb == this);241242if (insn->prev)243insn->prev->next = insn->next;244245if (insn->next)246insn->next->prev = insn->prev;247else248exit = insn->prev;249250if (insn == entry) {251if (insn->next)252entry = insn->next;253else254if (insn->prev && insn->prev->op != OP_PHI)255entry = insn->prev;256else257entry = NULL;258}259260if (insn == phi)261phi = (insn->next && insn->next->op == OP_PHI) ? insn->next : 0;262263--numInsns;264insn->bb = NULL;265insn->next =266insn->prev = NULL;267}268269void BasicBlock::permuteAdjacent(Instruction *a, Instruction *b)270{271assert(a->bb == b->bb);272273if (a->next != b) {274Instruction *i = a;275a = b;276b = i;277}278assert(a->next == b);279assert(a->op != OP_PHI && b->op != OP_PHI);280281if (b == exit)282exit = a;283if (a == entry)284entry = b;285286b->prev = a->prev;287a->next = b->next;288b->next = a;289a->prev = b;290291if (b->prev)292b->prev->next = b;293if (a->next)294a->next->prev = a;295}296297void298BasicBlock::splitCommon(Instruction *insn, BasicBlock *bb, bool attach)299{300bb->entry = insn;301302if (insn) {303exit = insn->prev;304insn->prev = NULL;305}306307if (exit)308exit->next = NULL;309else310entry = NULL;311312while (!cfg.outgoing(true).end()) {313Graph::Edge *e = cfg.outgoing(true).getEdge();314bb->cfg.attach(e->getTarget(), e->getType());315this->cfg.detach(e->getTarget());316}317318for (; insn; insn = insn->next) {319this->numInsns--;320bb->numInsns++;321insn->bb = bb;322bb->exit = insn;323}324if (attach)325this->cfg.attach(&bb->cfg, Graph::Edge::TREE);326}327328BasicBlock *329BasicBlock::splitBefore(Instruction *insn, bool attach)330{331BasicBlock *bb = new BasicBlock(func);332assert(!insn || insn->op != OP_PHI);333334bb->joinAt = joinAt;335joinAt = NULL;336337splitCommon(insn, bb, attach);338return bb;339}340341BasicBlock *342BasicBlock::splitAfter(Instruction *insn, bool attach)343{344BasicBlock *bb = new BasicBlock(func);345assert(!insn || insn->op != OP_PHI);346347bb->joinAt = joinAt;348joinAt = NULL;349350splitCommon(insn ? insn->next : NULL, bb, attach);351return bb;352}353354bool355BasicBlock::dominatedBy(BasicBlock *that)356{357Graph::Node *bn = &that->dom;358Graph::Node *dn = &this->dom;359360while (dn && dn != bn)361dn = dn->parent();362363return dn != NULL;364}365366unsigned int367BasicBlock::initiatesSimpleConditional() const368{369Graph::Node *out[2];370int n;371Graph::Edge::Type eR;372373if (cfg.outgoingCount() != 2) // -> if and -> else/endif374return false;375376n = 0;377for (Graph::EdgeIterator ei = cfg.outgoing(); !ei.end(); ei.next())378out[n++] = ei.getNode();379eR = out[1]->outgoing().getType();380381// IF block is out edge to the right382if (eR == Graph::Edge::CROSS || eR == Graph::Edge::BACK)383return 0x2;384385if (out[1]->outgoingCount() != 1) // 0 is IF { RET; }, >1 is more divergence386return 0x0;387// do they reconverge immediately ?388if (out[1]->outgoing().getNode() == out[0])389return 0x1;390if (out[0]->outgoingCount() == 1)391if (out[0]->outgoing().getNode() == out[1]->outgoing().getNode())392return 0x3;393394return 0x0;395}396397bool398Function::setEntry(BasicBlock *bb)399{400if (cfg.getRoot())401return false;402cfg.insert(&bb->cfg);403return true;404}405406bool407Function::setExit(BasicBlock *bb)408{409if (cfgExit)410return false;411cfgExit = &bb->cfg;412return true;413}414415unsigned int416Function::orderInstructions(ArrayList &result)417{418result.clear();419420for (IteratorRef it = cfg.iteratorCFG(); !it->end(); it->next()) {421BasicBlock *bb =422BasicBlock::get(reinterpret_cast<Graph::Node *>(it->get()));423424for (Instruction *insn = bb->getFirst(); insn; insn = insn->next)425result.insert(insn, insn->serial);426}427428return result.getSize();429}430431void432Function::buildLiveSets()433{434for (unsigned i = 0; i <= loopNestingBound; ++i)435buildLiveSetsPreSSA(BasicBlock::get(cfg.getRoot()), cfg.nextSequence());436437for (ArrayList::Iterator bi = allBBlocks.iterator(); !bi.end(); bi.next())438BasicBlock::get(bi)->liveSet.marker = false;439}440441void442Function::buildDefSets()443{444for (unsigned i = 0; i <= loopNestingBound; ++i)445buildDefSetsPreSSA(BasicBlock::get(cfgExit), cfg.nextSequence());446447for (ArrayList::Iterator bi = allBBlocks.iterator(); !bi.end(); bi.next())448BasicBlock::get(bi)->liveSet.marker = false;449}450451bool452Pass::run(Program *prog, bool ordered, bool skipPhi)453{454this->prog = prog;455err = false;456return doRun(prog, ordered, skipPhi);457}458459bool460Pass::doRun(Program *prog, bool ordered, bool skipPhi)461{462for (IteratorRef it = prog->calls.iteratorDFS(false);463!it->end(); it->next()) {464Graph::Node *n = reinterpret_cast<Graph::Node *>(it->get());465if (!doRun(Function::get(n), ordered, skipPhi))466return false;467}468return !err;469}470471bool472Pass::run(Function *func, bool ordered, bool skipPhi)473{474prog = func->getProgram();475err = false;476return doRun(func, ordered, skipPhi);477}478479bool480Pass::doRun(Function *func, bool ordered, bool skipPhi)481{482IteratorRef bbIter;483BasicBlock *bb;484Instruction *insn, *next;485486this->func = func;487if (!visit(func))488return false;489490bbIter = ordered ? func->cfg.iteratorCFG() : func->cfg.iteratorDFS();491492for (; !bbIter->end(); bbIter->next()) {493bb = BasicBlock::get(reinterpret_cast<Graph::Node *>(bbIter->get()));494if (!visit(bb))495break;496for (insn = skipPhi ? bb->getEntry() : bb->getFirst(); insn != NULL;497insn = next) {498next = insn->next;499if (!visit(insn))500break;501}502}503504return !err;505}506507void508Function::printCFGraph(const char *filePath)509{510FILE *out = fopen(filePath, "a");511if (!out) {512ERROR("failed to open file: %s\n", filePath);513return;514}515INFO("printing control flow graph to: %s\n", filePath);516517fprintf(out, "digraph G {\n");518519for (IteratorRef it = cfg.iteratorDFS(); !it->end(); it->next()) {520BasicBlock *bb = BasicBlock::get(521reinterpret_cast<Graph::Node *>(it->get()));522int idA = bb->getId();523for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {524int idB = BasicBlock::get(ei.getNode())->getId();525switch (ei.getType()) {526case Graph::Edge::TREE:527fprintf(out, "\t%i -> %i;\n", idA, idB);528break;529case Graph::Edge::FORWARD:530fprintf(out, "\t%i -> %i [color=green];\n", idA, idB);531break;532case Graph::Edge::CROSS:533fprintf(out, "\t%i -> %i [color=red];\n", idA, idB);534break;535case Graph::Edge::BACK:536fprintf(out, "\t%i -> %i;\n", idA, idB);537break;538default:539assert(0);540break;541}542}543}544545fprintf(out, "}\n");546fclose(out);547}548549} // namespace nv50_ir550551552