/** * In 'prog' remove instruction[i] if removeFlags[i] == TRUE. * \return number of instructions removed */ static GLuint remove_instructions(struct gl_program *prog, const GLboolean *removeFlags) { GLint i, removeEnd = 0, removeCount = 0; GLuint totalRemoved = 0; /* go backward */ for (i = prog->NumInstructions - 1; i >= 0; i--) { if (removeFlags[i]) { totalRemoved++; if (removeCount == 0) { /* begin a run of instructions to remove */ removeEnd = i; removeCount = 1; } else { /* extend the run of instructions to remove */ removeCount++; } } else { /* don't remove this instruction, but check if the preceeding * instructions are to be removed. */ if (removeCount > 0) { GLint removeStart = removeEnd - removeCount + 1; _mesa_delete_instructions(prog, removeStart, removeCount); removeStart = removeCount = 0; /* reset removal info */ } } } return totalRemoved; }
/** * Handle one instruction. */ static void process_instruction(struct nqssadce_state* s) { struct prog_instruction *inst = s->Program->Instructions + s->IP; if (inst->Opcode == OPCODE_END) return; if (inst->Opcode != OPCODE_KIL) { if (s->Descr->RewriteDepthOut) { if (inst->DstReg.File == PROGRAM_OUTPUT && inst->DstReg.Index == FRAG_RESULT_DEPR) rewrite_depth_out(inst); } struct register_state *regstate = get_reg_state(s, inst->DstReg.File, inst->DstReg.Index); if (!regstate) { _mesa_problem(s->Ctx, "NqssaDce: bad destination register (%i[%i])\n", inst->DstReg.File, inst->DstReg.Index); return; } inst->DstReg.WriteMask &= regstate->Sourced; regstate->Sourced &= ~inst->DstReg.WriteMask; if (inst->DstReg.WriteMask == 0) { _mesa_delete_instructions(s->Program, s->IP, 1); return; } if (inst->DstReg.File == PROGRAM_TEMPORARY && !regstate->Sourced) unalias_temporary(s, inst->DstReg.Index); } /* Attention: Due to swizzle emulation code, the following * might change the instruction stream under us, so we have * to be careful with the inst pointer. */ switch (inst->Opcode) { case OPCODE_DDX: case OPCODE_DDY: case OPCODE_FRC: case OPCODE_MOV: inst = track_used_srcreg(s, inst, 0, inst->DstReg.WriteMask); break; case OPCODE_ADD: case OPCODE_MAX: case OPCODE_MIN: case OPCODE_MUL: inst = track_used_srcreg(s, inst, 0, inst->DstReg.WriteMask); inst = track_used_srcreg(s, inst, 1, inst->DstReg.WriteMask); break; case OPCODE_CMP: case OPCODE_MAD: inst = track_used_srcreg(s, inst, 0, inst->DstReg.WriteMask); inst = track_used_srcreg(s, inst, 1, inst->DstReg.WriteMask); inst = track_used_srcreg(s, inst, 2, inst->DstReg.WriteMask); break; case OPCODE_COS: case OPCODE_EX2: case OPCODE_LG2: case OPCODE_RCP: case OPCODE_RSQ: case OPCODE_SIN: inst = track_used_srcreg(s, inst, 0, 0x1); break; case OPCODE_DP3: inst = track_used_srcreg(s, inst, 0, 0x7); inst = track_used_srcreg(s, inst, 1, 0x7); break; case OPCODE_DP4: inst = track_used_srcreg(s, inst, 0, 0xf); inst = track_used_srcreg(s, inst, 1, 0xf); break; case OPCODE_KIL: case OPCODE_TEX: case OPCODE_TXB: case OPCODE_TXP: inst = track_used_srcreg(s, inst, 0, 0xf); break; default: _mesa_problem(s->Ctx, "NqssaDce: Unknown opcode %d\n", inst->Opcode); return; } }