mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 04:10:09 +01:00
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.
This commit is contained in:
parent
9bb36d54a2
commit
a3dd45e1c2
2 changed files with 87 additions and 0 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue