From 8cbded63fba06263eee0c231eca3594d0d35a1c6 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Thu, 18 Feb 2021 16:56:16 -0500 Subject: [PATCH] pan/bi: Make bi_writemask take a destination Assuming it's only the first destination breaks assumptions across the compiler. Add a destination source and fix up the many corresponding issues. Nothing to backport as far as I understand since multidest instruction are new. Signed-off-by: Alyssa Rosenzweig Reviewed-by: Boris Brezillon Part-of: --- src/panfrost/bifrost/bi_liveness.c | 5 ++++- src/panfrost/bifrost/bi_opt_dce.c | 21 ++++++++++++------- src/panfrost/bifrost/bi_ra.c | 41 ++++++++++++++++---------------------- src/panfrost/bifrost/bir.c | 6 +++--- src/panfrost/bifrost/compiler.h | 2 +- 5 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/panfrost/bifrost/bi_liveness.c b/src/panfrost/bifrost/bi_liveness.c index 2b8c569..828e434 100644 --- a/src/panfrost/bifrost/bi_liveness.c +++ b/src/panfrost/bifrost/bi_liveness.c @@ -29,7 +29,10 @@ bi_liveness_ins_update(uint16_t *live, bi_instr *ins, unsigned max) { /* live_in[s] = GEN[s] + (live_out[s] - KILL[s]) */ - pan_liveness_kill(live, bi_get_node(ins->dest[0]), max, bi_writemask(ins)); + bi_foreach_dest(ins, d) { + pan_liveness_kill(live, bi_get_node(ins->dest[d]), max, + bi_writemask(ins, d)); + } bi_foreach_src(ins, src) { unsigned count = bi_count_read_registers(ins, src); diff --git a/src/panfrost/bifrost/bi_opt_dce.c b/src/panfrost/bifrost/bi_opt_dce.c index 4605d20..39fc5d7 100644 --- a/src/panfrost/bifrost/bi_opt_dce.c +++ b/src/panfrost/bifrost/bi_opt_dce.c @@ -47,15 +47,22 @@ bi_opt_dead_code_eliminate(bi_context *ctx, bool soft) uint16_t *live = mem_dup(block->base.live_out, temp_count * sizeof(uint16_t)); bi_foreach_instr_in_block_safe_rev(block, ins) { - unsigned index = bi_get_node(ins->dest[0]); + bool all_null = true; - if (index < temp_count && !(live[index] & bi_writemask(ins))) { - if (soft || bi_side_effects(ins->op)) - ins->dest[0] = bi_null(); - else - bi_remove_instruction(ins); + bi_foreach_dest(ins, d) { + unsigned index = bi_get_node(ins->dest[d]); - progress |= true; + if (index < temp_count && !(live[index] & bi_writemask(ins, d))) { + ins->dest[d] = bi_null(); + progress = true; + } + + all_null &= bi_is_null(ins->dest[d]); + } + + if (all_null && !soft && !bi_side_effects(ins->op)) { + bi_remove_instruction(ins); + progress = true; } bi_liveness_ins_update(live, ins, temp_count); diff --git a/src/panfrost/bifrost/bi_ra.c b/src/panfrost/bifrost/bi_ra.c index eb77e35..9e89207 100644 --- a/src/panfrost/bifrost/bi_ra.c +++ b/src/panfrost/bifrost/bi_ra.c @@ -42,11 +42,10 @@ bi_mark_sr_live(bi_block *block, bi_clause *clause, unsigned node_count, uint16_ bi_foreach_instr_in_clause(block, clause, ins) { if (!bi_opcode_props[ins->op].sr_write) continue; - bi_foreach_dest(ins, d) { - unsigned node = bi_get_node(ins->dest[d]); - if (node < node_count) - live[node] = bi_writemask(ins); - } + /* Set liveness for dest 0 which is the staging register */ + unsigned node = bi_get_node(ins->dest[0]); + if (node < node_count) + live[node] = bi_writemask(ins, 0); break; } @@ -66,7 +65,7 @@ bi_mark_interference(bi_block *block, bi_clause *clause, struct lcra_state *l, u for (unsigned i = 0; i < node_count; ++i) { if (live[i]) { lcra_add_node_interference(l, bi_get_node(ins->dest[d]), - bi_writemask(ins), i, live[i]); + bi_writemask(ins, d), i, live[i]); } } } @@ -229,18 +228,6 @@ bi_rewrite_index_src_single(bi_instr *ins, bi_index old, bi_index new) } } -static void -bi_rewrite_index_dst_single(bi_instr *ins, bi_index old, bi_index new) -{ - bi_foreach_dest(ins, i) { - if (bi_is_equiv(ins->dest[i], old)) { - ins->dest[i].type = new.type; - ins->dest[i].reg = new.reg; - ins->dest[i].value = new.value; - } - } -} - /* If register allocation fails, find the best spill node */ static signed @@ -306,12 +293,18 @@ bi_clause_mark_spill(bi_context *ctx, bi_block *block, unsigned channels = 0; bi_foreach_instr_in_clause(block, clause, ins) { - if (!bi_is_equiv(ins->dest[0], index)) continue; - if (bi_is_null(*temp)) *temp = bi_temp_reg(ctx); - ins->no_spill = true; - bi_rewrite_index_dst_single(ins, index, *temp); - unsigned newc = util_last_bit(bi_writemask(ins)) >> 2; - channels = MAX2(channels, newc); + bi_foreach_dest(ins, d) { + if (!bi_is_equiv(ins->dest[d], index)) continue; + if (bi_is_null(*temp)) *temp = bi_temp_reg(ctx); + ins->no_spill = true; + + unsigned offset = ins->dest[d].offset; + ins->dest[d] = bi_replace_index(ins->dest[d], *temp); + ins->dest[d].offset = offset; + + unsigned newc = util_last_bit(bi_writemask(ins, d)) >> 2; + channels = MAX2(channels, newc); + } } return channels; diff --git a/src/panfrost/bifrost/bir.c b/src/panfrost/bifrost/bir.c index 567c7c1..3a62f55 100644 --- a/src/panfrost/bifrost/bir.c +++ b/src/panfrost/bifrost/bir.c @@ -93,12 +93,12 @@ bi_count_read_registers(bi_instr *ins, unsigned s) } unsigned -bi_writemask(bi_instr *ins) +bi_writemask(bi_instr *ins, unsigned d) { /* Assume we write a scalar */ unsigned mask = 0xF; - if (bi_opcode_props[ins->op].sr_write) { + if (d == 0 && bi_opcode_props[ins->op].sr_write) { unsigned count = bi_count_staging_registers(ins); /* TODO: this special case is even more special, TEXC has a @@ -109,7 +109,7 @@ bi_writemask(bi_instr *ins) mask = (1 << (count * 4)) - 1; } - unsigned shift = ins->dest[0].offset * 4; /* 32-bit words */ + unsigned shift = ins->dest[d].offset * 4; /* 32-bit words */ return (mask << shift); } diff --git a/src/panfrost/bifrost/compiler.h b/src/panfrost/bifrost/compiler.h index 9a82d0f..044a562 100644 --- a/src/panfrost/bifrost/compiler.h +++ b/src/panfrost/bifrost/compiler.h @@ -730,7 +730,7 @@ pan_next_block(pan_block *block) bool bi_has_arg(bi_instr *ins, bi_index arg); unsigned bi_count_read_registers(bi_instr *ins, unsigned src); -unsigned bi_writemask(bi_instr *ins); +unsigned bi_writemask(bi_instr *ins, unsigned dest); bi_clause * bi_next_clause(bi_context *ctx, pan_block *block, bi_clause *clause); bool bi_side_effects(enum bi_opcode op); -- 2.7.4