浏览代码

mesa: Fix up the remove_dead_code pass to operate on a channel basis.

This cleans up a bunch of instructions in GLSL programs to have limited
writemasks, which would translate to wins in shaders that hit the i965
brw_wm_glsl.c path by depending less on in-driver optimizations.  It will
also help hit other optimization passes I'm looking at.
tags/mesa_7_7_rc1
Eric Anholt 16 年前
父节点
当前提交
ee0a9e6e10
共有 1 个文件被更改,包括 56 次插入28 次删除
  1. 56
    28
      src/mesa/shader/prog_optimize.c

+ 56
- 28
src/mesa/shader/prog_optimize.c 查看文件

@@ -187,11 +187,10 @@ _mesa_consolidate_registers(struct gl_program *prog)
static void
_mesa_remove_dead_code(struct gl_program *prog)
{
GLboolean tempWritten[MAX_PROGRAM_TEMPS], tempRead[MAX_PROGRAM_TEMPS];
GLboolean tempRead[MAX_PROGRAM_TEMPS][4];
GLboolean *removeInst; /* per-instruction removal flag */
GLuint i, rem;
GLuint i, rem = 0, comp;

memset(tempWritten, 0, sizeof(tempWritten));
memset(tempRead, 0, sizeof(tempRead));

if (dbg) {
@@ -217,11 +216,27 @@ _mesa_remove_dead_code(struct gl_program *prog)
if (inst->SrcReg[j].RelAddr) {
if (dbg)
_mesa_printf("abort remove dead code (indirect temp)\n");
_mesa_free(removeInst);
return;
goto done;
}

tempRead[index] = GL_TRUE;
for (comp = 0; comp < 4; comp++) {
GLuint swz = (inst->SrcReg[j].Swizzle >> (3 * comp)) & 0x7;

switch (swz) {
case SWIZZLE_X:
tempRead[index][0] = GL_TRUE;
break;
case SWIZZLE_Y:
tempRead[index][1] = GL_TRUE;
break;
case SWIZZLE_Z:
tempRead[index][2] = GL_TRUE;
break;
case SWIZZLE_W:
tempRead[index][3] = GL_TRUE;
break;
}
}
}
}

@@ -233,50 +248,63 @@ _mesa_remove_dead_code(struct gl_program *prog)
if (inst->DstReg.RelAddr) {
if (dbg)
_mesa_printf("abort remove dead code (indirect temp)\n");
_mesa_free(removeInst);
return;
goto done;
}

tempWritten[index] = GL_TRUE;
if (inst->CondUpdate) {
/* If we're writing to this register and setting condition
* codes we cannot remove the instruction. Prevent removal
* by setting the 'read' flag.
*/
tempRead[index] = GL_TRUE;
tempRead[index][0] = GL_TRUE;
tempRead[index][1] = GL_TRUE;
tempRead[index][2] = GL_TRUE;
tempRead[index][3] = GL_TRUE;
}
}
}

if (dbg) {
for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
if (tempWritten[i] && !tempRead[i])
_mesa_printf("Remove writes to tmp %u\n", i);
}
}

/* find instructions that write to dead registers, flag for removal */
for (i = 0; i < prog->NumInstructions; i++) {
const struct prog_instruction *inst = prog->Instructions + i;
if (inst->DstReg.File == PROGRAM_TEMPORARY) {
GLint index = inst->DstReg.Index;
removeInst[i] = (tempWritten[index] && !tempRead[index]);
if (dbg && removeInst[i]) {
_mesa_printf("Remove inst %u: ", i);
_mesa_print_instruction(inst);
}
struct prog_instruction *inst = prog->Instructions + i;
const GLuint numDst = _mesa_num_inst_dst_regs(inst->Opcode);

if (numDst != 0 && inst->DstReg.File == PROGRAM_TEMPORARY) {
GLint chan, index = inst->DstReg.Index;

for (chan = 0; chan < 4; chan++) {
if (!tempRead[index][chan] &&
inst->DstReg.WriteMask & (1 << chan)) {
if (dbg) {
_mesa_printf("Remove writemask on %u.%c\n", i,
chan == 3 ? 'w' : 'x' + chan);
}
inst->DstReg.WriteMask &= ~(1 << chan);
rem++;
}
}

if (inst->DstReg.WriteMask == 0) {
/* If we cleared all writes, the instruction can be removed. */
if (dbg)
_mesa_printf("Remove instruction %u: \n", i);
removeInst[i] = GL_TRUE;
}
}
}

/* now remove the instructions which aren't needed */
rem = remove_instructions(prog, removeInst);

_mesa_free(removeInst);

if (dbg) {
_mesa_printf("Optimize: End dead code removal. %u instructions removed\n", rem);
_mesa_printf("Optimize: End dead code removal.\n");
_mesa_printf(" %u channel writes removed\n", rem);
_mesa_printf(" %u instructions removed\n", rem);
/*_mesa_print_program(prog);*/
}

done:
_mesa_free(removeInst);
}



正在加载...
取消
保存