From a3dd45e1c27e4e55dadb9467c2ea428f58083ac1 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 6 Apr 2012 19:08:27 +0200 Subject: [PATCH] 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. --- src/gallium/drivers/nv50/codegen/nv50_ir.h | 4 + .../nv50/codegen/nv50_ir_from_tgsi.cpp | 83 +++++++++++++++++++ 2 files changed, 87 insertions(+) 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 ins; + std::deque outs; + std::deque 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 inline void + updateCallArgs(Instruction *i, void (Instruction::*setArg)(int, Value *), + T (Function::*proto)); + + template 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 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 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; } -- 2.30.2