nv50/ir/tgsi: Replace the inlining logic with proper function calls.
This commit is contained in:
parent
56d40aa51b
commit
9bb36d54a2
|
@ -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 ||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue