Module: Mesa Branch: staging/21.2 Commit: 8e4d6692f303a0cb55c18f8282f9491992acb74a URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=8e4d6692f303a0cb55c18f8282f9491992acb74a
Author: Connor Abbott <[email protected]> Date: Fri Jul 23 11:56:14 2021 +0200 ir3/ra: Fix available bitset for live-through collect srcs When we mark live-through sources that are merged with the destination as killed, we kept the bitsets in sync, but we forgot to keep them in sync when unmarking them after allocating the destination. The result was that "available" wasn't correct for any instruction afterwards. This resulted in a bad register allocation with IR3_SHADER_DEBUG=spillall for a dEQP-VK test. While we're changing this, use ra_foreach_src(). Fixes: 0ffcb19b9d9 ("ir3: Rewrite register allocation") Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12033> (cherry picked from commit 70c22d38945223fbdef699c8af60f8be95b178c8) --- .pick_status.json | 2 +- src/freedreno/ir3/ir3_ra.c | 33 +++++++++++++++++++-------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 72d09ae36b1..73ec49fe575 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1138,7 +1138,7 @@ "description": "ir3/ra: Fix available bitset for live-through collect srcs", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "0ffcb19b9d9fbe902224542047c389a661fbf816" }, diff --git a/src/freedreno/ir3/ir3_ra.c b/src/freedreno/ir3/ir3_ra.c index 6463b62ed2a..60eab79971f 100644 --- a/src/freedreno/ir3/ir3_ra.c +++ b/src/freedreno/ir3/ir3_ra.c @@ -548,6 +548,18 @@ ra_file_mark_killed(struct ra_file *file, struct ra_interval *interval) interval->is_killed = true; } +static void +ra_file_unmark_killed(struct ra_file *file, struct ra_interval *interval) +{ + assert(!interval->interval.parent); + + for (physreg_t i = interval->physreg_start; i < interval->physreg_end; i++) { + BITSET_CLEAR(file->available, i); + } + + interval->is_killed = false; +} + static physreg_t ra_interval_get_physreg(const struct ra_interval *interval) { @@ -1311,15 +1323,11 @@ handle_collect(struct ra_ctx *ctx, struct ir3_instruction *instr) */ physreg_t dst_fixed = (physreg_t)~0u; - for (unsigned i = 0; i < instr->srcs_count; i++) { - if (!ra_reg_is_src(instr->srcs[i])) - continue; - - if (instr->srcs[i]->flags & IR3_REG_FIRST_KILL) { - mark_src_killed(ctx, instr->srcs[i]); + ra_foreach_src (src, instr) { + if (src->flags & IR3_REG_FIRST_KILL) { + mark_src_killed(ctx, src); } - struct ir3_register *src = instr->srcs[i]; struct ra_interval *interval = &ctx->intervals[src->def->name]; if (src->def->merge_set != dst_set || interval->is_killed) @@ -1347,11 +1355,7 @@ handle_collect(struct ra_ctx *ctx, struct ir3_instruction *instr) allocate_dst(ctx, instr->dsts[0]); /* Remove the temporary is_killed we added */ - for (unsigned i = 0; i < instr->srcs_count; i++) { - if (!ra_reg_is_src(instr->srcs[i])) - continue; - - struct ir3_register *src = instr->srcs[i]; + ra_foreach_src (src, instr) { struct ra_interval *interval = &ctx->intervals[src->def->name]; while (interval->interval.parent != NULL) { interval = ir3_reg_interval_to_ra_interval(interval->interval.parent); @@ -1359,8 +1363,9 @@ handle_collect(struct ra_ctx *ctx, struct ir3_instruction *instr) /* Filter out cases where it actually should be killed */ if (interval != &ctx->intervals[src->def->name] || - !(src->flags & IR3_REG_KILL)) - interval->is_killed = false; + !(src->flags & IR3_REG_KILL)) { + ra_file_unmark_killed(ra_get_file(ctx, src), interval); + } } ra_foreach_src_rev (src, instr) {
