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) {