@@ -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+
40834102int
40844103SchedDataCalculatorGM107::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