pan/midgard: Add dead move elimination pass

This is a special case of DCE designed to run after the out-of-ssa pass
to cleanup special register lowering.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
This commit is contained in:
Alyssa Rosenzweig 2019-07-25 14:43:32 -07:00
parent 082485d663
commit 10324095d2
2 changed files with 44 additions and 0 deletions

View file

@ -503,5 +503,6 @@ bool midgard_opt_copy_prop(compiler_context *ctx, midgard_block *block);
bool midgard_opt_combine_projection(compiler_context *ctx, midgard_block *block);
bool midgard_opt_varying_projection(compiler_context *ctx, midgard_block *block);
bool midgard_opt_dead_code_eliminate(compiler_context *ctx, midgard_block *block);
bool midgard_opt_dead_move_eliminate(compiler_context *ctx, midgard_block *block);
#endif

View file

@ -44,3 +44,46 @@ midgard_opt_dead_code_eliminate(compiler_context *ctx, midgard_block *block)
return progress;
}
/* Removes dead moves, that is, moves with a destination overwritten before
* being read. Normally handled implicitly as part of DCE, but this has to run
* after the out-of-SSA pass */
bool
midgard_opt_dead_move_eliminate(compiler_context *ctx, midgard_block *block)
{
bool progress = false;
mir_foreach_instr_in_block_safe(block, ins) {
if (ins->type != TAG_ALU_4) continue;
if (ins->compact_branch) continue;
if (!OP_IS_MOVE(ins->alu.op)) continue;
/* Check if it's overwritten in this block before being read */
bool overwritten = false;
mir_foreach_instr_in_block_from(block, q, mir_next_op(ins)) {
if (q->compact_branch) continue;
/* Check if used */
if (mir_has_arg(q, ins->ssa_args.dest))
break;
/* Check if overwritten */
if (q->ssa_args.dest == ins->ssa_args.dest) {
/* Special case to vec4; component tracking is
* harder */
overwritten = (q->mask == 0xF);
break;
}
}
if (overwritten) {
mir_remove_instruction(ins);
progress = true;
}
}
return progress;
}