panfrost/midgard: Extend copy propagation pass

This extends copy propagation to respect output modifiers for ALU
instructions, as well as potentially fixing some bugs related to looping
(all dEQP loop tests pass).

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
Alyssa Rosenzweig 2019-04-25 03:18:34 +00:00
parent 7bc91b487b
commit b53b4573c3
1 changed files with 48 additions and 8 deletions

View File

@ -3123,6 +3123,36 @@ midgard_opt_dead_code_eliminate(compiler_context *ctx, midgard_block *block)
return progress;
}
/* Combines the two outmods if possible. Returns whether the combination was
* successful */
static bool
midgard_combine_outmod(midgard_outmod *main, midgard_outmod overlay)
{
if (overlay == midgard_outmod_none)
return true;
if (*main == overlay)
return true;
if (*main == midgard_outmod_none) {
*main = overlay;
return true;
}
if (*main == midgard_outmod_pos && overlay == midgard_outmod_sat) {
*main = midgard_outmod_sat;
return true;
}
if (overlay == midgard_outmod_pos && *main == midgard_outmod_sat) {
*main = midgard_outmod_sat;
return true;
}
return false;
}
static bool
midgard_opt_copy_prop(compiler_context *ctx, midgard_block *block)
{
@ -3139,8 +3169,12 @@ midgard_opt_copy_prop(compiler_context *ctx, midgard_block *block)
if (to >= SSA_FIXED_MINIMUM) continue;
if (from >= SSA_FIXED_MINIMUM) continue;
if (to >= ctx->func->impl->ssa_alloc) continue;
if (from >= ctx->func->impl->ssa_alloc) continue;
/* Also, if the move has side effects, we're helpless */
/* Also, if the move has source side effects, we're not sure
* what to do. Destination side effects we can handle, though.
*/
midgard_vector_alu_src src =
vector_alu_from_unsigned(ins->alu.src2);
@ -3149,17 +3183,23 @@ midgard_opt_copy_prop(compiler_context *ctx, midgard_block *block)
if (mir_nontrivial_mod(src, is_int, mask)) continue;
mir_foreach_instr_in_block_from(block, v, mir_next_op(ins)) {
if (v->ssa_args.src0 == to) {
v->ssa_args.src0 = from;
progress = true;
}
mir_foreach_instr_in_block_from_rev(block, v, mir_prev_op(ins)) {
if (v->ssa_args.dest == from) {
if (v->type == TAG_ALU_4) {
midgard_outmod final = v->alu.outmod;
if (v->ssa_args.src1 == to && !v->ssa_args.inline_constant) {
v->ssa_args.src1 = from;
if (!midgard_combine_outmod(&final, ins->alu.outmod))
continue;
v->alu.outmod = final;
}
v->ssa_args.dest = to;
progress = true;
}
}
mir_remove_instruction(ins);
}
return progress;