From 05749542384abc4d4776bfe2a386b6396002e0df Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 1 Oct 2009 14:52:28 -0600 Subject: mesa: fix mem leaks --- src/mesa/shader/prog_optimize.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/mesa/shader/prog_optimize.c') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index be903106a0..9d937488e3 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -217,6 +217,7 @@ _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; } @@ -232,6 +233,7 @@ _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; } @@ -422,6 +424,8 @@ _mesa_remove_extra_moves(struct gl_program *prog) /* now remove the instructions which aren't needed */ rem = remove_instructions(prog, removeInst); + _mesa_free(removeInst); + if (dbg) { _mesa_printf("Optimize: End remove extra moves. %u instructions removed\n", rem); /*_mesa_print_program(prog);*/ -- cgit v1.2.3 From ee0a9e6e10060287747d9dd4afead3cbbb168e09 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 12 Jun 2009 12:37:25 -0700 Subject: 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. --- src/mesa/shader/prog_optimize.c | 84 +++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 28 deletions(-) (limited to 'src/mesa/shader/prog_optimize.c') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index 9d937488e3..e627715b5a 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/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); } -- cgit v1.2.3 From e4e312d493847e07ced026b93d2b588b8036ae02 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 16 May 2009 01:47:44 -0700 Subject: mesa: Add an optimization path to remove use of pointless MOVs. GLSL code such as: vec4 result = {0, 1, 0, 0}; gl_FragColor = result; emits code like: 0: MOV TEMP[0], CONST[0]; 1: MOV OUTPUT[1], TEMP[0]; and this replaces it with: 0: MOV TEMP[0], CONST[0]; 1: MOV OUTPUT[1], CONST[0]; Even when the dead code eliminator fails to clean up a now-useless MOV instruction (since it doesn't do live/dead ranges), this should at reduce dependencies. --- src/mesa/shader/prog_optimize.c | 84 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) (limited to 'src/mesa/shader/prog_optimize.c') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index e627715b5a..5aff16be46 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -38,7 +38,6 @@ static GLboolean dbg = GL_FALSE; - /** * In 'prog' remove instruction[i] if removeFlags[i] == TRUE. * \return number of instructions removed @@ -354,6 +353,87 @@ find_next_temp_use(const struct gl_program *prog, GLuint start, GLuint index) } +/** + * Try to remove use of extraneous MOV instructions, to free them up for dead + * code removal. + */ +static void +_mesa_remove_extra_move_use(struct gl_program *prog) +{ + GLuint i; + + if (dbg) { + _mesa_printf("Optimize: Begin remove extra move use\n"); + _mesa_print_program(prog); + } + + /* + * Look for sequences such as this: + * MOV tmpX, arg0; + * FOO tmpY, tmpX, arg1; + * and convert into: + * MOV tmpX, arg0; + * FOO tmpY, arg0, arg1; + */ + + for (i = 0; i < prog->NumInstructions - 1; i++) { + const struct prog_instruction *mov = prog->Instructions + i; + struct prog_instruction *inst2 = prog->Instructions + i + 1; + int arg; + + if (mov->Opcode != OPCODE_MOV || + mov->DstReg.File != PROGRAM_TEMPORARY || + mov->DstReg.RelAddr || + mov->DstReg.CondMask != COND_TR || + mov->SaturateMode != SATURATE_OFF) + continue; + + for (arg = 0; arg < _mesa_num_inst_src_regs(inst2->Opcode); arg++) { + int comp; + + if (inst2->SrcReg[arg].File != mov->DstReg.File || + inst2->SrcReg[arg].Index != mov->DstReg.Index || + inst2->SrcReg[arg].RelAddr || + inst2->SrcReg[arg].Abs) + continue; + + /* Check that all the sources for this arg of inst2 come from inst1 + * or constants. + */ + for (comp = 0; comp < 4; comp++) { + 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 && + (mov->DstReg.WriteMask & (1 << src_swz)) == 0) + break; + } + if (comp != 4) + continue; + + /* Adjust the swizzles of inst2 to point at MOV's source */ + for (comp = 0; comp < 4; comp++) { + int inst2_swz = GET_SWZ(inst2->SrcReg[arg].Swizzle, comp); + + if (inst2_swz <= SWIZZLE_W) { + GLuint s = GET_SWZ(mov->SrcReg[0].Swizzle, inst2_swz); + inst2->SrcReg[arg].Swizzle &= ~(7 << (3 * comp)); + inst2->SrcReg[arg].Swizzle |= s << (3 * comp); + inst2->SrcReg[arg].Negate ^= (((mov->SrcReg[0].Negate >> + inst2_swz) & 0x1) << comp); + } + } + inst2->SrcReg[arg].File = mov->SrcReg[0].File; + inst2->SrcReg[arg].Index = mov->SrcReg[0].Index; + } + } + + if (dbg) { + _mesa_printf("Optimize: End remove extra move use.\n"); + /*_mesa_print_program(prog);*/ + } +} + /** * Try to remove extraneous MOV instructions from the given program. */ @@ -851,6 +931,8 @@ _mesa_reallocate_registers(struct gl_program *prog) void _mesa_optimize_program(GLcontext *ctx, struct gl_program *program) { + _mesa_remove_extra_move_use(program); + if (1) _mesa_remove_dead_code(program); -- cgit v1.2.3 From f3cacfe216fb58b913bbc23de49d696a33da69e1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 6 Nov 2009 13:04:54 -0800 Subject: mesa: Fix remove_instructions to successfully remove when removeFlags[0]. This fixes the dead code elimination to work on the particular code mentioned in the previous commit. --- src/mesa/shader/prog_optimize.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/mesa/shader/prog_optimize.c') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index 5aff16be46..b4658cb37f 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -73,6 +73,12 @@ remove_instructions(struct gl_program *prog, const GLboolean *removeFlags) } } } + /* Finish removing if the first instruction was 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; } -- cgit v1.2.3 From 6b0bcfafab7b380ee71da1a7754f4c09614811d6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 6 Nov 2009 14:06:08 -0800 Subject: 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. --- src/mesa/shader/prog_optimize.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'src/mesa/shader/prog_optimize.c') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index b4658cb37f..94d3dce6ea 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; } -- cgit v1.2.3 From 18768393d19dedee7d4282e84905bb396dd30960 Mon Sep 17 00:00:00 2001 From: brian Date: Sat, 7 Nov 2009 08:18:03 -0700 Subject: mesa: move code after decl Fixes bug 24967. --- src/mesa/shader/prog_optimize.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mesa/shader/prog_optimize.c') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index 94d3dce6ea..8638754e24 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -249,8 +249,9 @@ _mesa_remove_dead_code(struct gl_program *prog) for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) { const GLuint index = inst->SrcReg[j].Index; + GLuint read_mask; ASSERT(index < MAX_PROGRAM_TEMPS); - int read_mask = get_src_arg_mask(inst, j); + read_mask = get_src_arg_mask(inst, j); if (inst->SrcReg[j].RelAddr) { if (dbg) -- cgit v1.2.3 From d6690ce15fb8c7c6abf1bc0d847c1d2da2c33904 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 11 Nov 2009 13:26:26 -0800 Subject: mesa: Improve the eliminate-move-use to work across multiple instructions. This shaves more instructions off of the VS of my GL demo, but no performance difference this time at n=6. This also fixes a regression that was in this path, which is now piglit's glsl-vs-mov-after-deref. --- src/mesa/shader/prog_optimize.c | 126 +++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 41 deletions(-) (limited to 'src/mesa/shader/prog_optimize.c') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index 8638754e24..3d28d885a4 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -65,6 +65,7 @@ get_src_arg_mask(const struct prog_instruction *inst, int arg) case OPCODE_DP2: return WRITEMASK_XY; case OPCODE_DP3: + case OPCODE_XPD: return WRITEMASK_XYZ; default: return WRITEMASK_XYZW; @@ -396,6 +397,26 @@ find_next_temp_use(const struct gl_program *prog, GLuint start, GLuint index) return END; } +static GLboolean _mesa_is_flow_control_opcode(enum prog_opcode opcode) +{ + switch (opcode) { + case OPCODE_BGNLOOP: + case OPCODE_BGNSUB: + case OPCODE_BRA: + case OPCODE_CAL: + case OPCODE_CONT: + case OPCODE_IF: + case OPCODE_ELSE: + case OPCODE_END: + case OPCODE_ENDIF: + case OPCODE_ENDLOOP: + case OPCODE_ENDSUB: + case OPCODE_RET: + return GL_TRUE; + default: + return GL_FALSE; + } +} /** * Try to remove use of extraneous MOV instructions, to free them up for dead @@ -404,7 +425,7 @@ find_next_temp_use(const struct gl_program *prog, GLuint start, GLuint index) static void _mesa_remove_extra_move_use(struct gl_program *prog) { - GLuint i; + GLuint i, j; if (dbg) { _mesa_printf("Optimize: Begin remove extra move use\n"); @@ -414,63 +435,86 @@ _mesa_remove_extra_move_use(struct gl_program *prog) /* * Look for sequences such as this: * MOV tmpX, arg0; + * ... * FOO tmpY, tmpX, arg1; * and convert into: * MOV tmpX, arg0; + * ... * FOO tmpY, arg0, arg1; */ for (i = 0; i < prog->NumInstructions - 1; i++) { const struct prog_instruction *mov = prog->Instructions + i; - struct prog_instruction *inst2 = prog->Instructions + i + 1; - int arg; if (mov->Opcode != OPCODE_MOV || mov->DstReg.File != PROGRAM_TEMPORARY || mov->DstReg.RelAddr || mov->DstReg.CondMask != COND_TR || - mov->SaturateMode != SATURATE_OFF) + mov->SaturateMode != SATURATE_OFF || + mov->SrcReg[0].RelAddr) continue; - 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 || - inst2->SrcReg[arg].RelAddr || - inst2->SrcReg[arg].Abs) - continue; - - /* Check that all the sources for this arg of inst2 come from inst1 - * or constants. - */ - for (comp = 0; comp < 4; comp++) { - int src_swz = GET_SWZ(inst2->SrcReg[arg].Swizzle, comp); - - /* If the MOV didn't write that channel, can't use it. */ - if ((read_mask & (1 << comp)) && - src_swz <= SWIZZLE_W && - (mov->DstReg.WriteMask & (1 << src_swz)) == 0) - break; - } - if (comp != 4) - continue; - - /* Adjust the swizzles of inst2 to point at MOV's source */ - for (comp = 0; comp < 4; comp++) { - int inst2_swz = GET_SWZ(inst2->SrcReg[arg].Swizzle, comp); - - if (inst2_swz <= SWIZZLE_W) { - GLuint s = GET_SWZ(mov->SrcReg[0].Swizzle, inst2_swz); - inst2->SrcReg[arg].Swizzle &= ~(7 << (3 * comp)); - inst2->SrcReg[arg].Swizzle |= s << (3 * comp); - inst2->SrcReg[arg].Negate ^= (((mov->SrcReg[0].Negate >> - inst2_swz) & 0x1) << comp); + /* Walk through remaining instructions until the or src reg gets + * rewritten or we get into some flow-control, eliminating the use of + * this MOV. + */ + for (j = i + 1; j < prog->NumInstructions; j++) { + struct prog_instruction *inst2 = prog->Instructions + j; + int arg; + + if (_mesa_is_flow_control_opcode(inst2->Opcode)) + break; + + /* First rewrite this instruction's args if appropriate. */ + 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 || + inst2->SrcReg[arg].RelAddr || + inst2->SrcReg[arg].Abs) + continue; + + /* Check that all the sources for this arg of inst2 come from inst1 + * or constants. + */ + for (comp = 0; comp < 4; comp++) { + int src_swz = GET_SWZ(inst2->SrcReg[arg].Swizzle, comp); + + /* If the MOV didn't write that channel, can't use it. */ + if ((read_mask & (1 << comp)) && + src_swz <= SWIZZLE_W && + (mov->DstReg.WriteMask & (1 << src_swz)) == 0) + break; + } + if (comp != 4) + continue; + + /* Adjust the swizzles of inst2 to point at MOV's source */ + for (comp = 0; comp < 4; comp++) { + int inst2_swz = GET_SWZ(inst2->SrcReg[arg].Swizzle, comp); + + if (inst2_swz <= SWIZZLE_W) { + GLuint s = GET_SWZ(mov->SrcReg[0].Swizzle, inst2_swz); + inst2->SrcReg[arg].Swizzle &= ~(7 << (3 * comp)); + inst2->SrcReg[arg].Swizzle |= s << (3 * comp); + inst2->SrcReg[arg].Negate ^= (((mov->SrcReg[0].Negate >> + inst2_swz) & 0x1) << comp); + } } + inst2->SrcReg[arg].File = mov->SrcReg[0].File; + inst2->SrcReg[arg].Index = mov->SrcReg[0].Index; } - inst2->SrcReg[arg].File = mov->SrcReg[0].File; - inst2->SrcReg[arg].Index = mov->SrcReg[0].Index; + + /* If this instruction overwrote part of the move, our time is up. */ + if ((inst2->DstReg.File == mov->DstReg.File && + (inst2->DstReg.RelAddr || + inst2->DstReg.Index == mov->DstReg.Index)) || + (inst2->DstReg.File == mov->SrcReg[0].File && + (inst2->DstReg.RelAddr || + inst2->DstReg.Index == mov->SrcReg[0].Index))) + break; } } -- cgit v1.2.3 From c4e8918cd248189d43cdc8df9f9f0450040261c5 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 20 Nov 2009 21:42:06 +0100 Subject: mesa: Fix NULL deref in optimizer when NumInstructions == 0. Bug #24984. --- src/mesa/shader/prog_optimize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/mesa/shader/prog_optimize.c') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index 3d28d885a4..4fe351251e 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -443,7 +443,7 @@ _mesa_remove_extra_move_use(struct gl_program *prog) * FOO tmpY, arg0, arg1; */ - for (i = 0; i < prog->NumInstructions - 1; i++) { + for (i = 0; i + 1 < prog->NumInstructions; i++) { const struct prog_instruction *mov = prog->Instructions + i; if (mov->Opcode != OPCODE_MOV || -- cgit v1.2.3