summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/panfrost/midgard/compiler.h1
-rw-r--r--src/panfrost/midgard/midgard_opt_dce.c49
-rw-r--r--src/panfrost/midgard/midgard_schedule.c6
3 files changed, 56 insertions, 0 deletions
diff --git a/src/panfrost/midgard/compiler.h b/src/panfrost/midgard/compiler.h
index 034a256589a..f3fd92ad50b 100644
--- a/src/panfrost/midgard/compiler.h
+++ b/src/panfrost/midgard/compiler.h
@@ -509,5 +509,6 @@ 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);
+void midgard_opt_post_move_eliminate(compiler_context *ctx, midgard_block *block, struct ra_graph *g);
#endif
diff --git a/src/panfrost/midgard/midgard_opt_dce.c b/src/panfrost/midgard/midgard_opt_dce.c
index 698650ab8ad..d0d8b1a1833 100644
--- a/src/panfrost/midgard/midgard_opt_dce.c
+++ b/src/panfrost/midgard/midgard_opt_dce.c
@@ -87,3 +87,52 @@ midgard_opt_dead_move_eliminate(compiler_context *ctx, midgard_block *block)
return progress;
}
+
+/* An even further special case - to be run after RA runs but before
+ * scheduling, eliminating moves that end up being useless even though they
+ * appeared meaningful in the SSA. Part #2 of register coalescing. */
+
+void
+midgard_opt_post_move_eliminate(compiler_context *ctx, midgard_block *block, struct ra_graph *g)
+{
+ 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 we're to the same place post-RA */
+ unsigned iA = ins->ssa_args.dest;
+ unsigned iB = ins->ssa_args.src1;
+
+ if ((iA < 0) || (iB < 0)) continue;
+
+ unsigned A = iA >= SSA_FIXED_MINIMUM ?
+ SSA_REG_FROM_FIXED(iA) :
+ ra_get_node_reg(g, iA);
+
+ unsigned B = iB >= SSA_FIXED_MINIMUM ?
+ SSA_REG_FROM_FIXED(iB) :
+ ra_get_node_reg(g, iB);
+
+ if (A != B) continue;
+ if (ins->ssa_args.inline_constant) continue;
+
+ /* Check we're in the work zone. TODO: promoted
+ * uniforms? */
+ if (A >= 16) continue;
+
+ /* Ensure there aren't side effects */
+ if (mir_nontrivial_source2_mod(ins)) continue;
+ if (mir_nontrivial_outmod(ins)) continue;
+ if (ins->mask != 0xF) continue;
+
+ /* We do want to rewrite to keep the graph sane for pipeline
+ * register creation (TODO: is this the best approach?) */
+ mir_rewrite_index_dst(ctx, ins->ssa_args.src1, ins->ssa_args.dest);
+
+ /* We're good to go */
+ mir_remove_instruction(ins);
+
+ }
+
+}
diff --git a/src/panfrost/midgard/midgard_schedule.c b/src/panfrost/midgard/midgard_schedule.c
index a2c0c76fb6e..6b689e4ee40 100644
--- a/src/panfrost/midgard/midgard_schedule.c
+++ b/src/panfrost/midgard/midgard_schedule.c
@@ -827,6 +827,12 @@ schedule_program(compiler_context *ctx)
g = allocate_registers(ctx, &spilled);
} while(spilled && ((iter_count--) > 0));
+ /* We can simplify a bit after RA */
+
+ mir_foreach_block(ctx, block) {
+ midgard_opt_post_move_eliminate(ctx, block, g);
+ }
+
/* After RA finishes, we schedule all at once */
mir_foreach_block(ctx, block) {