Skip to content

Commit 818c939

Browse files
committed
codegen: track dual-issued texture dependencies via a shared counter (Maxwell)
1 parent 5a5afc2 commit 818c939

1 file changed

Lines changed: 83 additions & 6 deletions

File tree

mesa-imported/codegen/nv50_ir_emit_gm107.cpp

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3853,6 +3853,8 @@ class SchedDataCalculatorGM107 : public Pass
38533853
inline void emitWrDepBar(Instruction *, uint8_t);
38543854
inline void emitRdDepBar(Instruction *, uint8_t);
38553855
inline void emitWtDepBar(Instruction *, uint8_t);
3856+
inline void clearWrDepBar(Instruction *);
3857+
inline void breakDualIssue(Instruction *);
38563858

38573859
inline int getStall(const Instruction *) const;
38583860
inline int getWrDepBar(const Instruction *) const;
@@ -4080,6 +4082,23 @@ SchedDataCalculatorGM107::commitInsn(const Instruction *insn, int cycle)
40804082
#define GM107_MIN_ISSUE_DELAY 0x1
40814083
#define GM107_MAX_ISSUE_DELAY 0xf
40824084

4085+
// All-ones value of a 3-bit dependency-barrier field, meaning "no barrier".
4086+
#define GM107_NO_DEP_BAR 0x7
4087+
4088+
inline void
4089+
SchedDataCalculatorGM107::clearWrDepBar(Instruction *insn)
4090+
{
4091+
insn->sched |= GM107_NO_DEP_BAR << 5; // set the write-dep barrier to none
4092+
}
4093+
4094+
inline void
4095+
SchedDataCalculatorGM107::breakDualIssue(Instruction *insn)
4096+
{
4097+
// Pull insn out of a dual-issue pair: clear its stall/yield and give it the
4098+
// minimum issue delay so its successor runs in its own slot.
4099+
insn->sched = (insn->sched & ~0x1f) | GM107_MIN_ISSUE_DELAY;
4100+
}
4101+
40834102
int
40844103
SchedDataCalculatorGM107::calcDelay(const Instruction *insn, int cycle) const
40854104
{
@@ -4312,6 +4331,7 @@ SchedDataCalculatorGM107::insertBarriers(BasicBlock *bb)
43124331
Instruction *insn, *next;
43134332
BitSet bars(6, 1);
43144333
int bar_id;
4334+
int texBar = -1; // shared texture-pipe counter barrier
43154335

43164336
for (insn = bb->getEntry(); insn != NULL; insn = next) {
43174337
Instruction *usei = NULL, *defi = NULL;
@@ -4325,7 +4345,8 @@ SchedDataCalculatorGM107::insertBarriers(BasicBlock *bb)
43254345
if (insn->serial >= it->usei->serial) {
43264346
int wr = getWrDepBar(it->insn);
43274347
emitWtDepBar(insn, wr);
4328-
bars.clr(wr); // free barrier
4348+
if (wr != texBar)
4349+
bars.clr(wr); // free barrier (texture counter stays reserved)
43294350
it = live_uses.erase(it);
43304351
continue;
43314352
}
@@ -4355,11 +4376,23 @@ SchedDataCalculatorGM107::insertBarriers(BasicBlock *bb)
43554376
// completing before this insn.
43564377
usei = findFirstUse(insn);
43574378

4358-
// Allocate and emit a new barrier.
4359-
bar_id = bars.findFreeRange(1);
4360-
if (bar_id == -1)
4361-
bar_id = 5;
4362-
bars.set(bar_id);
4379+
// Allocate and emit a new barrier. Textures share one counter barrier
4380+
// (consumers wait for it to drain) because a per-texture write barrier
4381+
// is unreliable when the texture is dual-issued.
4382+
if (targ->getOpClass(insn->op) == OPCLASS_TEXTURE) {
4383+
if (texBar == -1) {
4384+
texBar = bars.findFreeRange(1);
4385+
if (texBar == -1)
4386+
texBar = 5;
4387+
bars.set(texBar);
4388+
}
4389+
bar_id = texBar;
4390+
} else {
4391+
bar_id = bars.findFreeRange(1);
4392+
if (bar_id == -1)
4393+
bar_id = 5;
4394+
bars.set(bar_id);
4395+
}
43634396
emitWrDepBar(insn, bar_id);
43644397
if (usei)
43654398
live_uses.push_back(LiveBarUse(insn, usei));
@@ -4494,6 +4527,50 @@ SchedDataCalculatorGM107::visit(BasicBlock *bb)
44944527
#endif
44954528
}
44964529

4530+
// A barrier issued from the second dual-issue slot is not honored by the
4531+
// texture unit, so a co-issued texture must set no barrier:
4532+
// - its write (result) barrier is offloaded to the shared texture counter,
4533+
// which a following texture keeps live (textures retire in order, so the
4534+
// counter wait covers this result too);
4535+
// - its read (coordinate) barrier cannot be offloaded, so a texture that
4536+
// needs one is un-dual-issued back into its own slot.
4537+
{
4538+
Instruction *prevInsn = NULL;
4539+
for (Instruction *t = bb->getEntry(); t != NULL; prevInsn = t, t = t->next) {
4540+
if (targ->getOpClass(t->op) != OPCLASS_TEXTURE)
4541+
continue;
4542+
if (!prevInsn || getStall(prevInsn) != 0)
4543+
continue; // not the second slot of a dual-issue
4544+
4545+
// Coordinate WAR (read barrier) can't be covered from the second slot.
4546+
if (getRdDepBar(t) != GM107_NO_DEP_BAR) {
4547+
breakDualIssue(prevInsn);
4548+
continue;
4549+
}
4550+
4551+
int wb = getWrDepBar(t);
4552+
if (wb == GM107_NO_DEP_BAR)
4553+
continue;
4554+
bool covered = false;
4555+
Instruction *jprev = t;
4556+
for (Instruction *j = t->next; j != NULL; jprev = j, j = j->next) {
4557+
if (getWtDepBar(j) & (1 << wb))
4558+
break; // counter drained before a covering texture
4559+
// The covering texture must keep its barrier, i.e. not be co-issued
4560+
// itself (a co-issued texture's barrier is dropped below).
4561+
if (targ->getOpClass(j->op) == OPCLASS_TEXTURE &&
4562+
getWrDepBar(j) != GM107_NO_DEP_BAR && getStall(jprev) != 0) {
4563+
covered = true;
4564+
break;
4565+
}
4566+
}
4567+
if (covered)
4568+
clearWrDepBar(t); // counter covers this result
4569+
else
4570+
breakDualIssue(prevInsn); // no cover: needs its own slot
4571+
}
4572+
}
4573+
44974574
if (!insn)
44984575
return true;
44994576
commitInsn(insn, cycle);

0 commit comments

Comments
 (0)