nv50/ir/tgsi: Replace the inlining logic with proper function calls.

This commit is contained in:
Francisco Jerez 2012-03-27 17:29:55 +02:00 committed by Christoph Bumiller
parent 56d40aa51b
commit 9bb36d54a2
5 changed files with 82 additions and 68 deletions

View File

@ -919,11 +919,13 @@ CmpInstruction::clone(ClonePolicy<Function>& pol, Instruction *i) const
return cmp;
}
FlowInstruction::FlowInstruction(Function *fn, operation op,
BasicBlock *targ)
FlowInstruction::FlowInstruction(Function *fn, operation op, void *targ)
: Instruction(fn, op, TYPE_NONE)
{
target.bb = targ;
if (op == OP_CALL)
target.fn = reinterpret_cast<Function *>(targ);
else
target.bb = reinterpret_cast<BasicBlock *>(targ);
if (op == OP_BRA ||
op == OP_CONT || op == OP_BREAK ||

View File

@ -818,7 +818,7 @@ public:
class FlowInstruction : public Instruction
{
public:
FlowInstruction(Function *, operation, BasicBlock *target);
FlowInstruction(Function *, operation, void *target);
virtual FlowInstruction *clone(ClonePolicy<Function>&,
Instruction * = NULL) const;

View File

@ -282,7 +282,7 @@ BuildUtil::mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc)
}
FlowInstruction *
BuildUtil::mkFlow(operation op, BasicBlock *targ, CondCode cc, Value *pred)
BuildUtil::mkFlow(operation op, void *targ, CondCode cc, Value *pred)
{
FlowInstruction *insn = new_FlowInstruction(func, op, targ);

View File

@ -76,8 +76,7 @@ public:
Value **def, Value **src);
Instruction *mkQuadop(uint8_t qop, Value *, uint8_t l, Value *, Value *);
FlowInstruction *mkFlow(operation, BasicBlock *target,
CondCode, Value *pred);
FlowInstruction *mkFlow(operation, void *target, CondCode, Value *pred);
Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);

View File

@ -578,11 +578,6 @@ public:
Source(struct nv50_ir_prog_info *);
~Source();
struct Subroutine
{
unsigned pc;
};
public:
bool scanSource();
unsigned fileSize(unsigned file) const { return scan.file_max[file] + 1; }
@ -605,9 +600,6 @@ public:
uint8_t *resourceTargets; // TGSI_TEXTURE_*
unsigned resourceCount;
Subroutine *subroutines;
unsigned subroutineCount;
private:
int inferSysValDirection(unsigned sn) const;
bool scanDeclaration(const struct tgsi_full_declaration *);
@ -626,7 +618,6 @@ Source::Source(struct nv50_ir_prog_info *prog) : info(prog)
tgsi_dump(tokens, 0);
resourceTargets = NULL;
subroutines = NULL;
mainTempsInLMem = FALSE;
}
@ -643,14 +634,11 @@ Source::~Source()
if (resourceTargets)
delete[] resourceTargets;
if (subroutines)
delete[] subroutines;
}
bool Source::scanSource()
{
unsigned insnCount = 0;
unsigned subrCount = 0;
struct tgsi_parse_context parse;
tgsi_scan_shader(tokens, &scan);
@ -665,9 +653,6 @@ bool Source::scanSource()
resourceCount = scan.file_max[TGSI_FILE_RESOURCE] + 1;
resourceTargets = new uint8_t[resourceCount];
subroutineCount = scan.opcode_count[TGSI_OPCODE_BGNSUB] + 1;
subroutines = new Subroutine[subroutineCount];
info->immd.bufSize = 0;
tempArrayCount = 0;
immdArrayCount = 0;
@ -700,10 +685,7 @@ bool Source::scanSource()
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
insns[insnCount++] = parse.FullToken.FullInstruction;
if (insns[insnCount - 1].Instruction.Opcode == TGSI_OPCODE_BGNSUB)
subroutines[++subrCount].pc = insnCount - 1;
else
scanInstruction(&parse.FullToken.FullInstruction);
scanInstruction(&parse.FullToken.FullInstruction);
break;
case TGSI_TOKEN_TYPE_PROPERTY:
scanProperty(&parse.FullToken.FullProperty);
@ -1028,6 +1010,13 @@ public:
bool run();
private:
struct Subroutine
{
Subroutine(Function *f) : f(f) { }
Function *f;
ValueMap values;
};
Value *getVertexBase(int s);
DataArray *getArrayForFile(unsigned file, int idx);
Value *fetchSrc(int s, int c);
@ -1046,6 +1035,8 @@ private:
bool handleInstruction(const struct tgsi_full_instruction *);
void exportOutputs();
inline Subroutine *getSubroutine(unsigned ip);
inline Subroutine *getSubroutine(Function *);
inline bool isEndOfSubroutine(uint ip);
void loadProjTexCoords(Value *dst[4], Value *src[4], unsigned int mask);
@ -1068,6 +1059,11 @@ private:
const struct tgsi::Source *code;
const struct nv50_ir_prog_info *info;
struct {
std::map<unsigned, Subroutine> map;
Subroutine *cur;
} sub;
uint ip; // instruction pointer
tgsi::Instruction tgsi;
@ -1082,8 +1078,6 @@ private:
std::vector<DataArray> lData; // TGSI_FILE_TEMPORARY_ARRAY
std::vector<DataArray> iData; // TGSI_FILE_IMMEDIATE_ARRAY
ValueMap values;
Value *zero;
Value *fragCoord[4];
Value *clipVtx[4];
@ -1095,9 +1089,6 @@ private:
Stack joinBBs; // fork BB, for inserting join ops on ENDIF
Stack loopBBs; // loop headers
Stack breakBBs; // end of / after loop
Stack entryBBs; // start of current (inlined) subroutine
Stack leaveBBs; // end of current (inlined) subroutine
Stack retIPs; // return instruction pointer
};
Symbol *
@ -1310,7 +1301,8 @@ Converter::fetchSrc(tgsi::Instruction::SrcRegister src, int c, Value *ptr)
assert(!ptr);
return mkOp1v(OP_RDSV, TYPE_U32, getSSA(), srcToSym(src, c));
default:
return getArrayForFile(src.getFile(), idx2d)->load(values, idx, swz, ptr);
return getArrayForFile(src.getFile(), idx2d)->load(
sub.cur->values, idx, swz, ptr);
}
}
@ -1331,7 +1323,7 @@ Converter::acquireDst(int d, int c)
(f == TGSI_FILE_OUTPUT && prog->getType() != Program::TYPE_FRAGMENT))
return getScratch();
return getArrayForFile(f, idx2d)-> acquire(values, idx, c);
return getArrayForFile(f, idx2d)-> acquire(sub.cur->values, idx, c);
}
void
@ -1387,7 +1379,7 @@ Converter::storeDst(const tgsi::Instruction::DstRegister dst, int c,
f == TGSI_FILE_PREDICATE ||
f == TGSI_FILE_ADDRESS ||
f == TGSI_FILE_OUTPUT) {
getArrayForFile(f, idx2d)->store(values, idx, c, ptr, val);
getArrayForFile(f, idx2d)->store(sub.cur->values, idx, c, ptr, val);
} else {
assert(!"invalid dst file");
}
@ -1654,6 +1646,30 @@ Converter::handleLIT(Value *dst0[4])
}
}
Converter::Subroutine *
Converter::getSubroutine(unsigned ip)
{
std::map<unsigned, Subroutine>::iterator it = sub.map.find(ip);
if (it == sub.map.end())
it = sub.map.insert(std::make_pair(
ip, Subroutine(new Function(prog, "SUB", ip)))).first;
return &it->second;
}
Converter::Subroutine *
Converter::getSubroutine(Function *f)
{
unsigned ip = f->getLabel();
std::map<unsigned, Subroutine>::iterator it = sub.map.find(ip);
if (it == sub.map.end())
it = sub.map.insert(std::make_pair(ip, Subroutine(f))).first;
return &it->second;
}
bool
Converter::isEndOfSubroutine(uint ip)
{
@ -2107,56 +2123,54 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
break;
case TGSI_OPCODE_BGNSUB:
{
if (!retIPs.getSize()) {
// end of main function
ip = code->scan.num_instructions - 2; // goto END
return true;
}
BasicBlock *entry = new BasicBlock(func);
BasicBlock *leave = new BasicBlock(func);
entryBBs.push(entry);
leaveBBs.push(leave);
bb->cfg.attach(&entry->cfg, Graph::Edge::TREE);
Subroutine *s = getSubroutine(ip);
BasicBlock *entry = new BasicBlock(s->f);
BasicBlock *leave = new BasicBlock(s->f);
// multiple entrypoints possible, keep the graph connected
if (prog->getType() == Program::TYPE_COMPUTE)
prog->main->call.attach(&s->f->call, Graph::Edge::TREE);
sub.cur = s;
s->f->setEntry(entry);
s->f->setExit(leave);
setPosition(entry, true);
}
return true;
}
case TGSI_OPCODE_ENDSUB:
{
BasicBlock *leave = reinterpret_cast<BasicBlock *>(leaveBBs.pop().u.p);
entryBBs.pop();
bb->cfg.attach(&leave->cfg, Graph::Edge::TREE);
setPosition(leave, true);
ip = retIPs.pop().u.u;
sub.cur = getSubroutine(prog->main);
setPosition(BasicBlock::get(sub.cur->f->cfg.getRoot()), true);
return true;
}
return true;
case TGSI_OPCODE_CAL:
// we don't have function declarations, so inline everything
retIPs.push(ip);
ip = code->subroutines[tgsi.getLabel()].pc - 1; // +1 after return
{
Subroutine *s = getSubroutine(tgsi.getLabel());
mkFlow(OP_CALL, s->f, CC_ALWAYS, NULL);
func->call.attach(&s->f->call, Graph::Edge::TREE);
return true;
}
case TGSI_OPCODE_RET:
{
if (bb->isTerminated())
return true;
BasicBlock *entry = reinterpret_cast<BasicBlock *>(entryBBs.peek().u.p);
BasicBlock *leave = reinterpret_cast<BasicBlock *>(leaveBBs.peek().u.p);
BasicBlock *leave = BasicBlock::get(func->cfgExit);
if (!isEndOfSubroutine(ip + 1)) {
// insert a PRERET at the entry if this is an early return
FlowInstruction *preRet = new_FlowInstruction(func, OP_PRERET, leave);
preRet->fixed = 1;
entry->insertHead(preRet);
// (only needed for sharing code in the epilogue)
mkFlow(OP_PRERET, leave, CC_ALWAYS, NULL)->fixed = 1;
bb->cfg.attach(&leave->cfg, Graph::Edge::CROSS);
}
// everything inlined so RET serves only to wrap up the stack
if (entry->getEntry() && entry->getEntry()->op == OP_PRERET)
} else {
mkFlow(OP_RET, NULL, CC_ALWAYS, NULL)->fixed = 1;
bb->cfg.attach(&leave->cfg, Graph::Edge::TREE);
}
}
break;
case TGSI_OPCODE_END:
{
// attach and generate epilogue code
BasicBlock *epilogue = reinterpret_cast<BasicBlock *>(leaveBBs.pop().u.p);
entryBBs.pop();
BasicBlock *epilogue = BasicBlock::get(func->cfgExit);
bb->cfg.attach(&epilogue->cfg, Graph::Edge::TREE);
setPosition(epilogue, true);
if (prog->getType() == Program::TYPE_FRAGMENT)
@ -2218,11 +2232,11 @@ Converter::exportOutputs()
{
for (unsigned int i = 0; i < info->numOutputs; ++i) {
for (unsigned int c = 0; c < 4; ++c) {
if (!oData.exists(values, i, c))
if (!oData.exists(sub.cur->values, i, c))
continue;
Symbol *sym = mkSymbol(FILE_SHADER_OUTPUT, 0, TYPE_F32,
info->out[i].slot[c] * 4);
Value *val = oData.load(values, i, c, NULL);
Value *val = oData.load(sub.cur->values, i, c, NULL);
if (val)
mkStore(OP_EXPORT, TYPE_F32, sym, NULL, val);
}
@ -2289,8 +2303,7 @@ Converter::run()
prog->main->setExit(leave);
setPosition(entry, true);
entryBBs.push(entry);
leaveBBs.push(leave);
sub.cur = getSubroutine(prog->main);
if (info->io.genUserClip > 0) {
for (int c = 0; c < 4; ++c)