mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-28 14:40:10 +01:00
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.
This commit is contained in:
parent
ee0a9e6e10
commit
e4e312d493
1 changed files with 83 additions and 1 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue