There's a special AL2P instruction (called AFETCH in nv50 ir) which computes a "physical" value to be used with indirect addressing with ALD. Fixes tcs-input-array-*-index-rd tcs-output-array-*-index-wr varying-indexing tessellation tests on Kepler. Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>tags/11.0-branchpoint
@@ -106,6 +106,7 @@ enum operation | |||
OP_MEMBAR, // memory barrier (mfence, lfence, sfence) | |||
OP_VFETCH, // indirection 0 in attribute space, indirection 1 is vertex base | |||
OP_PFETCH, // fetch base address of vertex src0 (immediate) [+ src1] | |||
OP_AFETCH, // fetch base address of shader input (a[%r1+0x10]) | |||
OP_EXPORT, | |||
OP_LINTERP, | |||
OP_PINTERP, |
@@ -77,6 +77,7 @@ private: | |||
void emitMOV(const Instruction *); | |||
void emitINTERP(const Instruction *); | |||
void emitAFETCH(const Instruction *); | |||
void emitPFETCH(const Instruction *); | |||
void emitVFETCH(const Instruction *); | |||
void emitEXPORT(const Instruction *); | |||
@@ -1338,6 +1339,23 @@ CodeEmitterGK110::emitFlow(const Instruction *i) | |||
} | |||
} | |||
void | |||
CodeEmitterGK110::emitAFETCH(const Instruction *i) | |||
{ | |||
uint32_t offset = i->src(0).get()->reg.data.offset & 0x7ff; | |||
code[0] = 0x00000002 | (offset << 23); | |||
code[1] = 0x7d000000 | (offset >> 9); | |||
if (i->getSrc(0)->reg.file == FILE_SHADER_OUTPUT) | |||
code[1] |= 0x8; | |||
emitPredicate(i); | |||
defId(i->def(0), 2); | |||
srcId(i->src(0).getIndirect(0), 10); | |||
} | |||
void | |||
CodeEmitterGK110::emitPFETCH(const Instruction *i) | |||
{ | |||
@@ -1707,6 +1725,9 @@ CodeEmitterGK110::emitInstruction(Instruction *insn) | |||
case OP_EXPORT: | |||
emitEXPORT(insn); | |||
break; | |||
case OP_AFETCH: | |||
emitAFETCH(insn); | |||
break; | |||
case OP_PFETCH: | |||
emitPFETCH(insn); | |||
break; |
@@ -174,6 +174,7 @@ private: | |||
void emitALD(); | |||
void emitAST(); | |||
void emitISBERD(); | |||
void emitAL2P(); | |||
void emitIPA(); | |||
void emitPIXLD(); | |||
@@ -2203,6 +2204,17 @@ CodeEmitterGM107::emitISBERD() | |||
emitGPR (0x00, insn->def(0)); | |||
} | |||
void | |||
CodeEmitterGM107::emitAL2P() | |||
{ | |||
emitInsn (0xefa00000); | |||
emitField(0x2f, 2, (insn->getDef(0)->reg.size / 4) - 1); | |||
emitO (0x20); | |||
emitField(0x14, 11, insn->src(0).get()->reg.data.offset); | |||
emitGPR (0x08, insn->src(0).getIndirect(0)); | |||
emitGPR (0x00, insn->def(0)); | |||
} | |||
void | |||
CodeEmitterGM107::emitIPA() | |||
{ | |||
@@ -2759,6 +2771,9 @@ CodeEmitterGM107::emitInstruction(Instruction *i) | |||
case OP_PFETCH: | |||
emitISBERD(); | |||
break; | |||
case OP_AFETCH: | |||
emitAL2P(); | |||
break; | |||
case OP_LINTERP: | |||
case OP_PINTERP: | |||
emitIPA(); |
@@ -85,6 +85,7 @@ private: | |||
void emitCCTL(const Instruction *); | |||
void emitINTERP(const Instruction *); | |||
void emitAFETCH(const Instruction *); | |||
void emitPFETCH(const Instruction *); | |||
void emitVFETCH(const Instruction *); | |||
void emitEXPORT(const Instruction *); | |||
@@ -1493,6 +1494,21 @@ CodeEmitterNVC0::emitBAR(const Instruction *i) | |||
} | |||
} | |||
void | |||
CodeEmitterNVC0::emitAFETCH(const Instruction *i) | |||
{ | |||
code[0] = 0x00000006; | |||
code[1] = 0x0c000000 | (i->src(0).get()->reg.data.offset & 0x7ff); | |||
if (i->getSrc(0)->reg.file == FILE_SHADER_OUTPUT) | |||
code[0] |= 0x200; | |||
emitPredicate(i); | |||
defId(i->def(0), 14); | |||
srcId(i->src(0).getIndirect(0), 20); | |||
} | |||
void | |||
CodeEmitterNVC0::emitPFETCH(const Instruction *i) | |||
{ |
@@ -1749,6 +1749,7 @@ NVC0LoweringPass::checkPredicate(Instruction *insn) | |||
bool | |||
NVC0LoweringPass::visit(Instruction *i) | |||
{ | |||
bool ret = true; | |||
bld.setPosition(i, false); | |||
if (i->cc != CC_ALWAYS) | |||
@@ -1780,7 +1781,8 @@ NVC0LoweringPass::visit(Instruction *i) | |||
case OP_SQRT: | |||
return handleSQRT(i); | |||
case OP_EXPORT: | |||
return handleEXPORT(i); | |||
ret = handleEXPORT(i); | |||
break; | |||
case OP_EMIT: | |||
case OP_RESTART: | |||
return handleOUT(i); | |||
@@ -1843,7 +1845,20 @@ NVC0LoweringPass::visit(Instruction *i) | |||
default: | |||
break; | |||
} | |||
return true; | |||
/* Kepler+ has a special opcode to compute a new base address to be used | |||
* for indirect loads. | |||
*/ | |||
if (targ->getChipset() >= NVISA_GK104_CHIPSET && !i->perPatch && | |||
(i->op == OP_VFETCH || i->op == OP_EXPORT) && i->src(0).isIndirect(0)) { | |||
Instruction *afetch = bld.mkOp1(OP_AFETCH, TYPE_U32, bld.getSSA(), | |||
cloneShallow(func, i->getSrc(0))); | |||
afetch->setIndirect(0, 0, i->getIndirect(0, 0)); | |||
i->src(0).get()->reg.data.offset = 0; | |||
i->setIndirect(0, 0, afetch->getDef(0)); | |||
} | |||
return ret; | |||
} | |||
bool |
@@ -135,6 +135,7 @@ const char *operationStr[OP_LAST + 1] = | |||
"membar", | |||
"vfetch", | |||
"pfetch", | |||
"afetch", | |||
"export", | |||
"linterp", | |||
"pinterp", |
@@ -41,7 +41,7 @@ const uint8_t Target::operationSrcNr[] = | |||
0, 0, 0, 0, 0, // BRA, CALL, RET, CONT, BREAK, | |||
0, 0, 0, // PRERET,CONT,BREAK | |||
0, 0, 0, 0, 0, 0, // BRKPT, JOINAT, JOIN, DISCARD, EXIT, MEMBAR | |||
1, 1, 2, 1, 2, // VFETCH, PFETCH, EXPORT, LINTERP, PINTERP | |||
1, 1, 1, 2, 1, 2, // VFETCH, PFETCH, AFETCH, EXPORT, LINTERP, PINTERP | |||
1, 1, // EMIT, RESTART | |||
1, 1, 1, // TEX, TXB, TXL, | |||
1, 1, 1, 1, 1, 1, 2, // TXF, TXQ, TXD, TXG, TXLQ, TEXCSAA, TEXPREP | |||
@@ -96,8 +96,8 @@ const OpClass Target::operationClass[] = | |||
OPCLASS_FLOW, OPCLASS_FLOW, | |||
// MEMBAR | |||
OPCLASS_CONTROL, | |||
// VFETCH, PFETCH, EXPORT | |||
OPCLASS_LOAD, OPCLASS_OTHER, OPCLASS_STORE, | |||
// VFETCH, PFETCH, AFETCH, EXPORT | |||
OPCLASS_LOAD, OPCLASS_OTHER, OPCLASS_OTHER, OPCLASS_STORE, | |||
// LINTERP, PINTERP | |||
OPCLASS_SFU, OPCLASS_SFU, | |||
// EMIT, RESTART |
@@ -118,7 +118,7 @@ void TargetNV50::initOpInfo() | |||
static const uint32_t shortForm[(OP_LAST + 31) / 32] = | |||
{ | |||
// MOV,ADD,SUB,MUL,MAD,SAD,L/PINTERP,RCP,TEX,TXF | |||
0x00014e40, 0x00000040, 0x00000498, 0x00000000 | |||
0x00014e40, 0x00000040, 0x00000930, 0x00000000 | |||
}; | |||
static const operation noDestList[] = | |||
{ |