ir3/ra: Fix bug with collect source handling
It can be the case that a collect and one of its sources are assigned
to non-overlapping parts of the same merge set, for example:
ssa_1 = ...
ssa_2 = ...
ssa_3 = ...
ssa_4 = collect ssa_1, ssa_2 (kill), ssa_3
... = ssa_4 (kill)
ssa_5 = collect ssa_1, ssa_3
... = ssa_1 (kill)
... = ssa_3 (kill)
... = ssa_5 (kill)
If we merge the first collect first, we get a merge set:
ssa_1 (offset 0)
ssa_2 (offset 2)
ssa_3 (offset 4)
ssa_4 (offset 0)
Now, we decide to merge ssa_1 and ssa_5:
ssa_1 (offset 0)
ssa_2 (offset 2)
ssa_3 (offset 4)
ssa_4 (offset 0)
ssa_5 (offset 0)
ssa_3 cannot become a child of ssa_5 in the interval tree, just like a
source not in the same merge set, so we should not remove it and then
reinsert it assuming that RA will make it a child of ssa_5.
This fixes an RA validation error in Farming Simulater.
Fixes: 0ffcb19
("ir3: Rewrite register allocation")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27497>
This commit is contained in:
@@ -1725,8 +1725,14 @@ handle_collect(struct ra_ctx *ctx, struct ir3_instruction *instr)
|
||||
|
||||
struct ra_interval *interval = &ctx->intervals[src->def->name];
|
||||
|
||||
if (src->def->merge_set != dst_set || interval->is_killed)
|
||||
/* We only need special handling if the source's interval overlaps with
|
||||
* the destination's interval.
|
||||
*/
|
||||
if (src->def->interval_start >= instr->dsts[0]->interval_end ||
|
||||
instr->dsts[0]->interval_start >= src->def->interval_end ||
|
||||
interval->is_killed)
|
||||
continue;
|
||||
|
||||
while (interval->interval.parent != NULL) {
|
||||
interval = ir3_reg_interval_to_ra_interval(interval->interval.parent);
|
||||
}
|
||||
|
Reference in New Issue
Block a user