diff options
author | Francisco Jerez <[email protected]> | 2012-04-06 19:08:27 +0200 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2012-04-14 21:54:02 +0200 |
commit | a3dd45e1c27e4e55dadb9467c2ea428f58083ac1 (patch) | |
tree | 252a9d1e039778d753f534418537aa0bc7964f7a /src/gallium/drivers/nv50/codegen | |
parent | 9bb36d54a2c69ebdc9d1c9c4c71945060de8c860 (diff) |
nv50/ir/tgsi: Infer function inputs/outputs.
Edit: Don't do it for the main function of (graphics) shaders,
its inputs and outputs always go through TGSI_FILE_INPUT/OUTPUT.
This prevents all TEMPs from counting as live out and reduces
register pressure.
Diffstat (limited to 'src/gallium/drivers/nv50/codegen')
-rw-r--r-- | src/gallium/drivers/nv50/codegen/nv50_ir.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp | 83 |
2 files changed, 87 insertions, 0 deletions
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.h b/src/gallium/drivers/nv50/codegen/nv50_ir.h index 0a8a0743eb4..b06d0938b62 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir.h +++ b/src/gallium/drivers/nv50/codegen/nv50_ir.h @@ -947,6 +947,10 @@ public: bool convertToSSA(); public: + std::deque<ValueDef> ins; + std::deque<ValueRef> outs; + std::deque<Value *> clobbers; + Graph cfg; Graph::Node *cfgExit; Graph *domTree; diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp index f4199c3a9b8..81d5d55f780 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp @@ -1055,6 +1055,27 @@ private: Value *buildDot(int dim); + class BindArgumentsPass : public Pass { + public: + BindArgumentsPass(Converter &conv) : conv(conv) { } + + private: + Converter &conv; + Subroutine *sub; + + template<typename T> inline void + updateCallArgs(Instruction *i, void (Instruction::*setArg)(int, Value *), + T (Function::*proto)); + + template<typename T> inline void + updatePrototype(BitSet *set, void (Function::*updateSet)(), + T (Function::*proto)); + + protected: + bool visit(Function *); + bool visit(BasicBlock *bb) { return false; } + }; + private: const struct tgsi::Source *code; const struct nv50_ir_prog_info *info; @@ -2293,6 +2314,64 @@ Converter::~Converter() { } +template<typename T> inline void +Converter::BindArgumentsPass::updateCallArgs( + Instruction *i, void (Instruction::*setArg)(int, Value *), + T (Function::*proto)) +{ + Function *g = i->asFlow()->target.fn; + Subroutine *subg = conv.getSubroutine(g); + + for (unsigned a = 0; a < (g->*proto).size(); ++a) { + Value *v = (g->*proto)[a].get(); + const Converter::Location &l = subg->values.l.find(v)->second; + Converter::DataArray *array = conv.getArrayForFile(l.array, l.arrayIdx); + + (i->*setArg)(a, array->acquire(sub->values, l.i, l.c)); + } +} + +template<typename T> inline void +Converter::BindArgumentsPass::updatePrototype( + BitSet *set, void (Function::*updateSet)(), T (Function::*proto)) +{ + (func->*updateSet)(); + + for (unsigned i = 0; i < set->getSize(); ++i) { + Value *v = func->getLValue(i); + + // only include values with a matching TGSI register + if (set->test(i) && sub->values.l.find(v) != sub->values.l.end()) + (func->*proto).push_back(v); + } +} + +bool +Converter::BindArgumentsPass::visit(Function *f) +{ + sub = conv.getSubroutine(f); + + for (ArrayList::Iterator bi = f->allBBlocks.iterator(); + !bi.end(); bi.next()) { + for (Instruction *i = BasicBlock::get(bi)->getFirst(); + i; i = i->next) { + if (i->op == OP_CALL && !i->asFlow()->builtin) { + updateCallArgs(i, &Instruction::setSrc, &Function::ins); + updateCallArgs(i, &Instruction::setDef, &Function::outs); + } + } + } + + if (func == prog->main && prog->getType() != Program::TYPE_COMPUTE) + return true; + updatePrototype(&BasicBlock::get(f->cfg.getRoot())->liveSet, + &Function::buildLiveSets, &Function::ins); + updatePrototype(&BasicBlock::get(f->cfgExit)->defSet, + &Function::buildDefSets, &Function::outs); + + return true; +} + bool Converter::run() { @@ -2320,6 +2399,10 @@ Converter::run() if (!handleInstruction(&code->insns[ip])) return false; } + + if (!BindArgumentsPass(*this).run(prog)) + return false; + return true; } |