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) {
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;
+ }
+ }
}
}
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);
}