pan/mdg: Fix reading a spilt register in the bundle it's written

Read directly from the instruction getting spilt. Otherwise a fill
will be inserted before the spill writing the value, so the
instruction reading the spilt value gets garbage data.

Use the bundle_id to check if the instructions are in the same bundle.

Insert a move instruction, as the spill needs the value in a LD/ST
register such as AL0, while the ALU instruction reading the value
needs it in a work register such as R0.

Cc: mesa-stable
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4857
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11212>
(cherry picked from commit 38e8d7afe3)
This commit is contained in:
Icecream95 2021-06-07 19:33:54 +12:00 committed by Eric Engestrom
parent 5c6f340bf5
commit b6d704d5a1
2 changed files with 30 additions and 2 deletions

View file

@ -346,7 +346,7 @@
"description": "pan/mdg: Fix reading a spilt register in the bundle it's written",
"nominated": true,
"nomination_type": 0,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null
},

View file

@ -896,9 +896,37 @@ mir_spill_register(
ins->dest = dest;
ins->no_spill |= (1 << spill_class);
bool move = false;
/* In the same bundle, reads of the destination
* of the spilt instruction need to be direct */
midgard_instruction *it = ins;
while ((it = list_first_entry(&it->link, midgard_instruction, link))
&& (it->bundle_id == ins->bundle_id)) {
if (!mir_has_arg(it, spill_node)) continue;
mir_rewrite_index_src_single(it, spill_node, dest);
/* The spilt instruction will write to
* a work register for `it` to read but
* the spill needs an LD/ST register */
move = true;
}
if (move)
dest = spill_index++;
midgard_instruction st =
v_load_store_scratch(ins->dest, spill_slot, true, ins->mask);
v_load_store_scratch(dest, spill_slot, true, ins->mask);
mir_insert_instruction_after_scheduled(ctx, block, ins, st);
if (move) {
midgard_instruction mv = v_mov(ins->dest, dest);
mv.no_spill |= (1 << spill_class);
mir_insert_instruction_after_scheduled(ctx, block, ins, mv);
}
}
if (!is_special)