aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorFrancisco Jerez <[email protected]>2012-03-27 17:29:55 +0200
committerChristoph Bumiller <[email protected]>2012-04-14 21:54:02 +0200
commit9bb36d54a2c69ebdc9d1c9c4c71945060de8c860 (patch)
tree106b5884ddf5d3a630767195e0f27560aeadbece /src/gallium
parent56d40aa51b34b77791cc3a49d7e86473a7459b72 (diff)
nv50/ir/tgsi: Replace the inlining logic with proper function calls.
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir.cpp8
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir.h2
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp2
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h3
-rw-r--r--src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp135
5 files changed, 82 insertions, 68 deletions
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir.cpp
index 698a1222263..314701bfb6a 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir.cpp
@@ -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 ||
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.h b/src/gallium/drivers/nv50/codegen/nv50_ir.h
index 93e3008cf0d..0a8a0743eb4 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir.h
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir.h
@@ -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;
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
index cb63854b043..dcae25bd508 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
@@ -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);
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h
index 69158861533..022a27f1748 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.h
@@ -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);
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 9f735bfb2e2..f4199c3a9b8 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
@@ -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;
+ }
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)