summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>2019-07-25 14:43:32 -0700
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>2019-07-26 08:37:08 -0700
commit10324095d2ee0e897a1bc41762d8fd8614ecd634 (patch)
tree13787791d7d8afc296bed3dcab8a91798e3f61be
parent082485d663301bbd1dfb14d9da11735f51c02fd0 (diff)
downloadmesa-10324095d2ee0e897a1bc41762d8fd8614ecd634.tar.gz
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>
-rw-r--r--src/panfrost/midgard/compiler.h1
-rw-r--r--src/panfrost/midgard/midgard_opt_dce.c43
2 files changed, 44 insertions, 0 deletions
diff --git a/src/panfrost/midgard/compiler.h b/src/panfrost/midgard/compiler.h
index 86b6e175454..32714d78d74 100644
--- a/src/panfrost/midgard/compiler.h
+++ b/src/panfrost/midgard/compiler.h
@@ -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
diff --git a/src/panfrost/midgard/midgard_opt_dce.c b/src/panfrost/midgard/midgard_opt_dce.c
index 6621c2fe2dd..698650ab8ad 100644
--- a/src/panfrost/midgard/midgard_opt_dce.c
+++ b/src/panfrost/midgard/midgard_opt_dce.c
@@ -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;
+}