ir3/spill: Fix extracting from a vector at the end of a block

If this happens then "after" is NULL, so we can't use it to get the
block, and the instruction is never moved at the end so we have to
create the split instructions before creating the collect to make sure
they are in the right order.

This happens when reloading a complex vector value that has been
coalesced at the end of a basic block, which apparently hasn't happened
until a gfxbench5 shader on zink hit this case. This fixes it.

Closes: #7054
Fixes: 613eaac7b5 ("ir3: Initial support for spilling non-shared registers")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18082>
This commit is contained in:
Connor Abbott 2022-08-16 14:38:59 +02:00 committed by Marge Bot
parent f9d7308014
commit dcfbb60392

View file

@ -854,7 +854,7 @@ split(struct ir3_register *def, unsigned offset,
assert(!(def->flags & IR3_REG_ARRAY));
assert(def->merge_set);
struct ir3_instruction *split =
ir3_instr_create(after->block, OPC_META_SPLIT, 1, 1);
ir3_instr_create(block, OPC_META_SPLIT, 1, 1);
struct ir3_register *dst = __ssa_dst(split);
dst->flags |= def->flags & IR3_REG_HALF;
struct ir3_register *src = ir3_src_create(split, INVALID_REG, def->flags);
@ -874,16 +874,20 @@ extract(struct ir3_register *parent_def, unsigned offset, unsigned elems,
if (offset == 0 && elems == reg_elems(parent_def))
return parent_def;
struct ir3_register *srcs[elems];
for (unsigned i = 0; i < elems; i++) {
srcs[i] = split(parent_def, offset + i, after, block);
}
struct ir3_instruction *collect =
ir3_instr_create(after->block, OPC_META_COLLECT, 1, elems);
ir3_instr_create(block, OPC_META_COLLECT, 1, elems);
struct ir3_register *dst = __ssa_dst(collect);
dst->flags |= parent_def->flags & IR3_REG_HALF;
dst->wrmask = MASK(elems);
add_to_merge_set(parent_def->merge_set, dst, parent_def->merge_set_offset);
for (unsigned i = 0; i < elems; i++) {
ir3_src_create(collect, INVALID_REG, parent_def->flags)->def =
split(parent_def, offset + i, after, block);
ir3_src_create(collect, INVALID_REG, parent_def->flags)->def = srcs[i];
}
if (after)