summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/prog_optimize.c
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2009-11-06 14:06:08 -0800
committerEric Anholt <[email protected]>2009-11-06 14:27:35 -0800
commit6b0bcfafab7b380ee71da1a7754f4c09614811d6 (patch)
tree36e28d738d7f33e8505ce719c9a2476c585e799a /src/mesa/shader/prog_optimize.c
parentf3cacfe216fb58b913bbc23de49d696a33da69e1 (diff)
mesa: Reduce the source channels considered in optimization passes.
Depending on the writemask or the opcode, we can often trim the source channels considered used for dead code elimination. This saves actual instructions on 965 in the non-GLSL path for glean glsl1, and cleans up the writemasks of programs even further.
Diffstat (limited to 'src/mesa/shader/prog_optimize.c')
-rw-r--r--src/mesa/shader/prog_optimize.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c
index b4658cb37f9..94d3dce6ea7 100644
--- a/src/mesa/shader/prog_optimize.c
+++ b/src/mesa/shader/prog_optimize.c
@@ -38,6 +38,39 @@
static GLboolean dbg = GL_FALSE;
+/* Returns the mask of channels read from the given srcreg in this instruction.
+ */
+static GLuint
+get_src_arg_mask(const struct prog_instruction *inst, int arg)
+{
+ int writemask = inst->DstReg.WriteMask;
+
+ if (inst->CondUpdate)
+ writemask = WRITEMASK_XYZW;
+
+ switch (inst->Opcode) {
+ case OPCODE_MOV:
+ case OPCODE_ABS:
+ case OPCODE_ADD:
+ case OPCODE_MUL:
+ case OPCODE_SUB:
+ return writemask;
+ case OPCODE_RCP:
+ case OPCODE_SIN:
+ case OPCODE_COS:
+ case OPCODE_RSQ:
+ case OPCODE_POW:
+ case OPCODE_EX2:
+ return WRITEMASK_X;
+ case OPCODE_DP2:
+ return WRITEMASK_XY;
+ case OPCODE_DP3:
+ return WRITEMASK_XYZ;
+ default:
+ return WRITEMASK_XYZW;
+ }
+}
+
/**
* In 'prog' remove instruction[i] if removeFlags[i] == TRUE.
* \return number of instructions removed
@@ -217,6 +250,7 @@ _mesa_remove_dead_code(struct gl_program *prog)
if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
const GLuint index = inst->SrcReg[j].Index;
ASSERT(index < MAX_PROGRAM_TEMPS);
+ int read_mask = get_src_arg_mask(inst, j);
if (inst->SrcReg[j].RelAddr) {
if (dbg)
@@ -227,6 +261,9 @@ _mesa_remove_dead_code(struct gl_program *prog)
for (comp = 0; comp < 4; comp++) {
GLuint swz = (inst->SrcReg[j].Swizzle >> (3 * comp)) & 0x7;
+ if ((read_mask & (1 << comp)) == 0)
+ continue;
+
switch (swz) {
case SWIZZLE_X:
tempRead[index][0] = GL_TRUE;
@@ -396,6 +433,7 @@ _mesa_remove_extra_move_use(struct gl_program *prog)
for (arg = 0; arg < _mesa_num_inst_src_regs(inst2->Opcode); arg++) {
int comp;
+ int read_mask = get_src_arg_mask(inst2, arg);
if (inst2->SrcReg[arg].File != mov->DstReg.File ||
inst2->SrcReg[arg].Index != mov->DstReg.Index ||
@@ -410,7 +448,8 @@ _mesa_remove_extra_move_use(struct gl_program *prog)
int src_swz = GET_SWZ(inst2->SrcReg[arg].Swizzle, comp);
/* If the MOV didn't write that channel, can't use it. */
- if (src_swz <= SWIZZLE_W &&
+ if ((read_mask & (1 << comp)) &&
+ src_swz <= SWIZZLE_W &&
(mov->DstReg.WriteMask & (1 << src_swz)) == 0)
break;
}