mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 20:00:10 +01:00
ir3/ra: prevent moving source intervals for shared collects
Non-trivial collects (i.e., ones that will introduce moves because the
sources don't line-up with the destination) may cause source intervals
to get implicitly moved when they are inserted as children of the
destination interval. Since we don't support moving intervals in shared
RA, this may cause illegal register allocations. Prevent this by
creating a new top-level interval for the destination so that the source
intervals will be left alone.
Signed-off-by: Job Noorman <jnoorman@igalia.com>
Fixes: fa22b0901a ("ir3/ra: Add specialized shared register RA/spilling")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31978>
This commit is contained in:
parent
a2c4a34303
commit
b36a7ce0f1
1 changed files with 35 additions and 1 deletions
|
|
@ -825,6 +825,24 @@ assign_src(struct ra_ctx *ctx, struct ir3_register *src)
|
||||||
interval->src = false;
|
interval->src = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_nontrivial_collect(struct ir3_instruction *collect)
|
||||||
|
{
|
||||||
|
if (collect->opc != OPC_META_COLLECT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ir3_register *dst = collect->dsts[0];
|
||||||
|
|
||||||
|
foreach_src_n (src, src_n, collect) {
|
||||||
|
if (src->num != dst->num + src_n) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_dst(struct ra_ctx *ctx, struct ir3_instruction *instr,
|
handle_dst(struct ra_ctx *ctx, struct ir3_instruction *instr,
|
||||||
struct ir3_register *dst)
|
struct ir3_register *dst)
|
||||||
|
|
@ -861,10 +879,26 @@ handle_dst(struct ra_ctx *ctx, struct ir3_instruction *instr,
|
||||||
free_space(ctx, physreg, size);
|
free_space(ctx, physreg, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dst->num = ra_physreg_to_num(physreg, dst->flags);
|
||||||
|
|
||||||
|
/* Non-trivial collects (i.e., ones that will introduce moves because the
|
||||||
|
* sources don't line-up with the destination) may cause source intervals to
|
||||||
|
* get implicitly moved when they are inserted as children of the destination
|
||||||
|
* interval. Since we don't support moving intervals in shared RA, this may
|
||||||
|
* cause illegal register allocations. Prevent this by creating a new
|
||||||
|
* top-level interval for the destination so that the source intervals will
|
||||||
|
* be left alone.
|
||||||
|
*/
|
||||||
|
if (is_nontrivial_collect(instr)) {
|
||||||
|
dst->merge_set = NULL;
|
||||||
|
dst->interval_start = ctx->live->interval_offset;
|
||||||
|
dst->interval_end = dst->interval_start + reg_size(dst);
|
||||||
|
ctx->live->interval_offset = dst->interval_end;
|
||||||
|
}
|
||||||
|
|
||||||
ra_update_affinity(reg_file_size(dst), dst, physreg);
|
ra_update_affinity(reg_file_size(dst), dst, physreg);
|
||||||
interval->physreg_start = physreg;
|
interval->physreg_start = physreg;
|
||||||
interval->physreg_end = physreg + reg_size(dst);
|
interval->physreg_end = physreg + reg_size(dst);
|
||||||
dst->num = ra_physreg_to_num(physreg, dst->flags);
|
|
||||||
ir3_reg_interval_insert(&ctx->reg_ctx, &interval->interval);
|
ir3_reg_interval_insert(&ctx->reg_ctx, &interval->interval);
|
||||||
d("insert dst %u physreg %u", dst->name, physreg);
|
d("insert dst %u physreg %u", dst->name, physreg);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue