Example #1
0
/**
 * 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;
	}
}